3 //============================================================================
6 #define PF_WARNING(s) do{Con_Printf(s);PRVM_PrintState();return;}while(0)
7 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
10 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 "
57 "DP_QC_FINDCHAINFLAGS "
58 "DP_QC_FINDCHAINFLOAT "
61 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
66 "DP_QC_MULTIPLETEMPSTRINGS "
68 "DP_QC_SINCOSSQRTPOW "
69 "DP_QC_STRINGBUFFERS "
72 "DP_QC_TRACE_MOVETYPE_HITMODEL "
73 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
74 "DP_QC_VECTORVECTORS "
80 "DP_SND_DIRECTIONLESSATTNNONE "
89 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
90 "DP_SV_DRAWONLYTOCLIENT "
93 "DP_SV_NODRAWTOCLIENT "
95 "DP_SV_PLAYERPHYSICS "
96 "DP_SV_PRECACHEANYTIME "
98 "DP_SV_ROTATINGBMODEL "
101 "DP_SV_WRITEUNTERMINATEDSTRING "
105 "DP_TE_EXPLOSIONRGB "
107 "DP_TE_PARTICLECUBE "
108 "DP_TE_PARTICLERAIN "
109 "DP_TE_PARTICLESNOW "
111 "DP_TE_QUADEFFECTS1 "
114 "DP_TE_STANDARDEFFECTBUILTINS "
115 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
118 //"EXT_CSQC " // not ready yet
120 "KRIMZON_SV_PARSECLIENTCOMMAND "
124 "PRYDON_CLIENTCURSOR "
125 "TENEBRAE_GFX_DLIGHTS "
127 "NEXUIZ_PLAYERMODEL "
134 Writes new values for v_forward, v_up, and v_right based on angles
138 void PF_makevectors (void)
140 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
147 This is the only valid way to move an object without using the physics of the world (setting velocity and waiting). Directly changing origin will not set internal links correctly, so clipping would be messed up. This should be called when an object is spawned, and then only if it is teleported.
149 setorigin (entity, origin)
152 void PF_setorigin (void)
157 e = PRVM_G_EDICT(OFS_PARM0);
158 if (e == prog->edicts)
159 PF_WARNING("setorigin: can not modify world entity\n");
160 if (e->priv.server->free)
161 PF_WARNING("setorigin: can not modify free entity\n");
162 org = PRVM_G_VECTOR(OFS_PARM1);
163 VectorCopy (org, e->fields.server->origin);
164 SV_LinkEdict (e, false);
168 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
172 for (i=0 ; i<3 ; i++)
174 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
176 // set derived values
177 VectorCopy (min, e->fields.server->mins);
178 VectorCopy (max, e->fields.server->maxs);
179 VectorSubtract (max, min, e->fields.server->size);
181 SV_LinkEdict (e, false);
188 the size box is rotated by the current angle
189 LordHavoc: no it isn't...
191 setsize (entity, minvector, maxvector)
194 void PF_setsize (void)
199 e = PRVM_G_EDICT(OFS_PARM0);
200 if (e == prog->edicts)
201 PF_WARNING("setsize: can not modify world entity\n");
202 if (e->priv.server->free)
203 PF_WARNING("setsize: can not modify free entity\n");
204 min = PRVM_G_VECTOR(OFS_PARM1);
205 max = PRVM_G_VECTOR(OFS_PARM2);
206 SetMinMaxSize (e, min, max, false);
214 setmodel(entity, model)
217 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
218 void PF_setmodel (void)
224 e = PRVM_G_EDICT(OFS_PARM0);
225 if (e == prog->edicts)
226 PF_WARNING("setmodel: can not modify world entity\n");
227 if (e->priv.server->free)
228 PF_WARNING("setmodel: can not modify free entity\n");
229 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
230 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
231 e->fields.server->modelindex = i;
237 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
238 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
240 SetMinMaxSize (e, quakemins, quakemaxs, true);
243 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
250 single print to a specific client
252 sprint(clientent, value)
255 void PF_sprint (void)
259 char string[VM_STRINGTEMP_LENGTH];
261 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
263 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
265 Con_Print("tried to sprint to a non-client\n");
269 client = svs.clients + entnum-1;
270 if (!client->netconnection)
273 VM_VarString(1, string, sizeof(string));
274 MSG_WriteChar(&client->netconnection->message,svc_print);
275 MSG_WriteString(&client->netconnection->message, string);
283 single print to a specific client
285 centerprint(clientent, value)
288 void PF_centerprint (void)
292 char string[VM_STRINGTEMP_LENGTH];
294 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
296 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
298 Con_Print("tried to sprint to a non-client\n");
302 client = svs.clients + entnum-1;
303 if (!client->netconnection)
306 VM_VarString(1, string, sizeof(string));
307 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
308 MSG_WriteString(&client->netconnection->message, string);
315 particle(origin, color, count)
318 void PF_particle (void)
324 org = PRVM_G_VECTOR(OFS_PARM0);
325 dir = PRVM_G_VECTOR(OFS_PARM1);
326 color = PRVM_G_FLOAT(OFS_PARM2);
327 count = PRVM_G_FLOAT(OFS_PARM3);
328 SV_StartParticle (org, dir, (int)color, (int)count);
338 void PF_ambientsound (void)
342 float vol, attenuation;
345 pos = PRVM_G_VECTOR (OFS_PARM0);
346 samp = PRVM_G_STRING(OFS_PARM1);
347 vol = PRVM_G_FLOAT(OFS_PARM2);
348 attenuation = PRVM_G_FLOAT(OFS_PARM3);
350 // check to see if samp was properly precached
351 soundnum = SV_SoundIndex(samp, 1);
359 // add an svc_spawnambient command to the level signon packet
362 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
364 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
366 MSG_WriteVector(&sv.signon, pos, sv.protocol);
369 MSG_WriteShort (&sv.signon, soundnum);
371 MSG_WriteByte (&sv.signon, soundnum);
373 MSG_WriteByte (&sv.signon, (int)(vol*255));
374 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
382 Each entity can have eight independant sound sources, like voice,
385 Channel 0 is an auto-allocate channel, the others override anything
386 already running on that entity/channel pair.
388 An attenuation of 0 will play full volume everywhere in the level.
389 Larger attenuations will drop off.
397 prvm_edict_t *entity;
401 entity = PRVM_G_EDICT(OFS_PARM0);
402 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
403 sample = PRVM_G_STRING(OFS_PARM2);
404 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
405 attenuation = PRVM_G_FLOAT(OFS_PARM4);
407 if (volume < 0 || volume > 255)
408 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
410 if (attenuation < 0 || attenuation > 4)
411 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
413 if (channel < 0 || channel > 7)
414 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
416 SV_StartSound (entity, channel, sample, volume, attenuation);
423 Used for use tracing and shot targeting
424 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
425 if the tryents flag is set.
427 traceline (vector1, vector2, tryents)
430 void PF_traceline (void)
438 prog->xfunction->builtinsprofile += 30;
440 v1 = PRVM_G_VECTOR(OFS_PARM0);
441 v2 = PRVM_G_VECTOR(OFS_PARM1);
442 move = (int)PRVM_G_FLOAT(OFS_PARM2);
443 ent = PRVM_G_EDICT(OFS_PARM3);
445 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]))
446 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));
448 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
450 prog->globals.server->trace_allsolid = trace.allsolid;
451 prog->globals.server->trace_startsolid = trace.startsolid;
452 prog->globals.server->trace_fraction = trace.fraction;
453 prog->globals.server->trace_inwater = trace.inwater;
454 prog->globals.server->trace_inopen = trace.inopen;
455 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
456 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
457 prog->globals.server->trace_plane_dist = trace.plane.dist;
459 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
461 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
462 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
463 val->_float = trace.startsupercontents;
464 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
465 val->_float = trace.hitsupercontents;
466 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
467 val->_float = trace.hitq3surfaceflags;
468 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
470 if (trace.hittexture)
472 char *s = VM_GetTempString();
473 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
474 val->string = PRVM_SetEngineString(s);
486 Used for use tracing and shot targeting
487 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
488 if the tryents flag is set.
490 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
493 // LordHavoc: added this for my own use, VERY useful, similar to traceline
494 void PF_tracebox (void)
496 float *v1, *v2, *m1, *m2;
502 prog->xfunction->builtinsprofile += 30;
504 v1 = PRVM_G_VECTOR(OFS_PARM0);
505 m1 = PRVM_G_VECTOR(OFS_PARM1);
506 m2 = PRVM_G_VECTOR(OFS_PARM2);
507 v2 = PRVM_G_VECTOR(OFS_PARM3);
508 move = (int)PRVM_G_FLOAT(OFS_PARM4);
509 ent = PRVM_G_EDICT(OFS_PARM5);
511 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]))
512 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));
514 trace = SV_Move (v1, m1, m2, v2, move, ent);
516 prog->globals.server->trace_allsolid = trace.allsolid;
517 prog->globals.server->trace_startsolid = trace.startsolid;
518 prog->globals.server->trace_fraction = trace.fraction;
519 prog->globals.server->trace_inwater = trace.inwater;
520 prog->globals.server->trace_inopen = trace.inopen;
521 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
522 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
523 prog->globals.server->trace_plane_dist = trace.plane.dist;
525 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
527 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
528 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
529 val->_float = trace.startsupercontents;
530 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
531 val->_float = trace.hitsupercontents;
532 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
533 val->_float = trace.hitq3surfaceflags;
534 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
536 if (trace.hittexture)
538 char *s = VM_GetTempString();
539 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
540 val->string = PRVM_SetEngineString(s);
547 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
548 void PF_tracetoss (void)
552 prvm_edict_t *ignore;
555 prog->xfunction->builtinsprofile += 600;
557 ent = PRVM_G_EDICT(OFS_PARM0);
558 if (ent == prog->edicts)
559 PF_WARNING("tracetoss: can not use world entity\n");
560 ignore = PRVM_G_EDICT(OFS_PARM1);
562 trace = SV_Trace_Toss (ent, ignore);
564 prog->globals.server->trace_allsolid = trace.allsolid;
565 prog->globals.server->trace_startsolid = trace.startsolid;
566 prog->globals.server->trace_fraction = trace.fraction;
567 prog->globals.server->trace_inwater = trace.inwater;
568 prog->globals.server->trace_inopen = trace.inopen;
569 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
570 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
571 prog->globals.server->trace_plane_dist = trace.plane.dist;
573 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
575 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
576 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
577 val->_float = trace.startsupercontents;
578 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
579 val->_float = trace.hitsupercontents;
580 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
581 val->_float = trace.hitq3surfaceflags;
582 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
584 if (trace.hittexture)
586 char *s = VM_GetTempString();
587 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
588 val->string = PRVM_SetEngineString(s);
600 Returns true if the given entity can move to the given position from it's
601 current position by walking or rolling.
603 scalar checkpos (entity, vector)
606 void PF_checkpos (void)
610 //============================================================================
613 unsigned char checkpvs[MAX_MAP_LEAFS/8];
615 int PF_newcheckclient (int check)
621 // cycle to the next one
623 check = bound(1, check, svs.maxclients);
624 if (check == svs.maxclients)
632 prog->xfunction->builtinsprofile++;
634 if (i == svs.maxclients+1)
636 // look up the client's edict
637 ent = PRVM_EDICT_NUM(i);
638 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
639 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
641 // found a valid client (possibly the same one again)
645 // get the PVS for the entity
646 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
648 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
649 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
658 Returns a client (or object that has a client enemy) that would be a
661 If there is more than one valid option, they are cycled each frame
663 If (self.origin + self.viewofs) is not in the PVS of the current target,
664 it is not returned at all.
669 int c_invis, c_notvis;
670 void PF_checkclient (void)
672 prvm_edict_t *ent, *self;
675 // find a new check if on a new frame
676 if (sv.time - sv.lastchecktime >= 0.1)
678 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
679 sv.lastchecktime = sv.time;
682 // return check if it might be visible
683 ent = PRVM_EDICT_NUM(sv.lastcheck);
684 if (ent->priv.server->free || ent->fields.server->health <= 0)
686 VM_RETURN_EDICT(prog->edicts);
690 // if current entity can't possibly see the check entity, return 0
691 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
692 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
693 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
696 VM_RETURN_EDICT(prog->edicts);
700 // might be able to see it
702 VM_RETURN_EDICT(ent);
705 //============================================================================
712 Sends text over to the client's execution buffer
714 stuffcmd (clientent, value, ...)
717 void PF_stuffcmd (void)
721 char string[VM_STRINGTEMP_LENGTH];
723 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
724 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
726 Con_Print("Can't stuffcmd to a non-client\n");
730 VM_VarString(1, string, sizeof(string));
733 host_client = svs.clients + entnum-1;
734 Host_ClientCommands ("%s", string);
742 Returns a chain of entities that have origins within a spherical area
744 findradius (origin, radius)
747 void PF_findradius (void)
749 prvm_edict_t *ent, *chain;
750 vec_t radius, radius2;
751 vec3_t org, eorg, mins, maxs;
754 prvm_edict_t *touchedicts[MAX_EDICTS];
756 chain = (prvm_edict_t *)prog->edicts;
758 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
759 radius = PRVM_G_FLOAT(OFS_PARM1);
760 radius2 = radius * radius;
762 mins[0] = org[0] - (radius + 1);
763 mins[1] = org[1] - (radius + 1);
764 mins[2] = org[2] - (radius + 1);
765 maxs[0] = org[0] + (radius + 1);
766 maxs[1] = org[1] + (radius + 1);
767 maxs[2] = org[2] + (radius + 1);
768 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
769 if (numtouchedicts > MAX_EDICTS)
771 // this never happens
772 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
773 numtouchedicts = MAX_EDICTS;
775 for (i = 0;i < numtouchedicts;i++)
777 ent = touchedicts[i];
778 prog->xfunction->builtinsprofile++;
779 // Quake did not return non-solid entities but darkplaces does
780 // (note: this is the reason you can't blow up fallen zombies)
781 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
783 // LordHavoc: compare against bounding box rather than center so it
784 // doesn't miss large objects, and use DotProduct instead of Length
785 // for a major speedup
786 VectorSubtract(org, ent->fields.server->origin, eorg);
787 if (sv_gameplayfix_findradiusdistancetobox.integer)
789 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
790 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
791 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
794 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
795 if (DotProduct(eorg, eorg) < radius2)
797 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
802 VM_RETURN_EDICT(chain);
805 void PF_precache_file (void)
806 { // precache_file is only used to copy files with qcc, it does nothing
807 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
811 void PF_precache_sound (void)
813 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
814 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
817 void PF_precache_model (void)
819 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
820 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
827 float(float yaw, float dist) walkmove
830 void PF_walkmove (void)
838 // assume failure if it returns early
839 PRVM_G_FLOAT(OFS_RETURN) = 0;
841 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
842 if (ent == prog->edicts)
843 PF_WARNING("walkmove: can not modify world entity\n");
844 if (ent->priv.server->free)
845 PF_WARNING("walkmove: can not modify free entity\n");
846 yaw = PRVM_G_FLOAT(OFS_PARM0);
847 dist = PRVM_G_FLOAT(OFS_PARM1);
849 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
852 yaw = yaw*M_PI*2 / 360;
854 move[0] = cos(yaw)*dist;
855 move[1] = sin(yaw)*dist;
858 // save program state, because SV_movestep may call other progs
859 oldf = prog->xfunction;
860 oldself = prog->globals.server->self;
862 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
865 // restore program state
866 prog->xfunction = oldf;
867 prog->globals.server->self = oldself;
877 void PF_droptofloor (void)
883 // assume failure if it returns early
884 PRVM_G_FLOAT(OFS_RETURN) = 0;
886 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
887 if (ent == prog->edicts)
888 PF_WARNING("droptofloor: can not modify world entity\n");
889 if (ent->priv.server->free)
890 PF_WARNING("droptofloor: can not modify free entity\n");
892 VectorCopy (ent->fields.server->origin, end);
895 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
897 if (trace.fraction != 1)
899 VectorCopy (trace.endpos, ent->fields.server->origin);
900 SV_LinkEdict (ent, false);
901 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
902 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
903 PRVM_G_FLOAT(OFS_RETURN) = 1;
904 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
905 ent->priv.server->suspendedinairflag = true;
913 void(float style, string value) lightstyle
916 void PF_lightstyle (void)
923 style = (int)PRVM_G_FLOAT(OFS_PARM0);
924 val = PRVM_G_STRING(OFS_PARM1);
926 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
927 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
930 // change the string in sv
931 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
933 // send message to all clients on this server
934 if (sv.state != ss_active)
937 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
939 if (client->active && client->netconnection)
941 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
942 MSG_WriteChar (&client->netconnection->message,style);
943 MSG_WriteString (&client->netconnection->message, val);
953 void PF_checkbottom (void)
955 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
963 void PF_pointcontents (void)
965 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
972 Pick a vector for the player to shoot along
973 vector aim(entity, missilespeed)
978 prvm_edict_t *ent, *check, *bestent;
979 vec3_t start, dir, end, bestdir;
982 float dist, bestdist;
985 // assume failure if it returns early
986 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
987 // if sv_aim is so high it can't possibly accept anything, skip out early
988 if (sv_aim.value >= 1)
991 ent = PRVM_G_EDICT(OFS_PARM0);
992 if (ent == prog->edicts)
993 PF_WARNING("aim: can not use world entity\n");
994 if (ent->priv.server->free)
995 PF_WARNING("aim: can not use free entity\n");
996 speed = PRVM_G_FLOAT(OFS_PARM1);
998 VectorCopy (ent->fields.server->origin, start);
1001 // try sending a trace straight
1002 VectorCopy (prog->globals.server->v_forward, dir);
1003 VectorMA (start, 2048, dir, end);
1004 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1005 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1006 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1008 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1013 // try all possible entities
1014 VectorCopy (dir, bestdir);
1015 bestdist = sv_aim.value;
1018 check = PRVM_NEXT_EDICT(prog->edicts);
1019 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1021 prog->xfunction->builtinsprofile++;
1022 if (check->fields.server->takedamage != DAMAGE_AIM)
1026 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1027 continue; // don't aim at teammate
1028 for (j=0 ; j<3 ; j++)
1029 end[j] = check->fields.server->origin[j]
1030 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1031 VectorSubtract (end, start, dir);
1032 VectorNormalize (dir);
1033 dist = DotProduct (dir, prog->globals.server->v_forward);
1034 if (dist < bestdist)
1035 continue; // to far to turn
1036 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1037 if (tr.ent == check)
1038 { // can shoot at this one
1046 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1047 dist = DotProduct (dir, prog->globals.server->v_forward);
1048 VectorScale (prog->globals.server->v_forward, dist, end);
1050 VectorNormalize (end);
1051 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1055 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1063 This was a major timewaster in progs, so it was converted to C
1066 void PF_changeyaw (void)
1069 float ideal, current, move, speed;
1071 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1072 if (ent == prog->edicts)
1073 PF_WARNING("changeyaw: can not modify world entity\n");
1074 if (ent->priv.server->free)
1075 PF_WARNING("changeyaw: can not modify free entity\n");
1076 current = ANGLEMOD(ent->fields.server->angles[1]);
1077 ideal = ent->fields.server->ideal_yaw;
1078 speed = ent->fields.server->yaw_speed;
1080 if (current == ideal)
1082 move = ideal - current;
1083 if (ideal > current)
1104 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1112 void PF_changepitch (void)
1115 float ideal, current, move, speed;
1118 ent = PRVM_G_EDICT(OFS_PARM0);
1119 if (ent == prog->edicts)
1120 PF_WARNING("changepitch: can not modify world entity\n");
1121 if (ent->priv.server->free)
1122 PF_WARNING("changepitch: can not modify free entity\n");
1123 current = ANGLEMOD( ent->fields.server->angles[0] );
1124 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1125 ideal = val->_float;
1128 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1131 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1132 speed = val->_float;
1135 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1139 if (current == ideal)
1141 move = ideal - current;
1142 if (ideal > current)
1163 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1167 ===============================================================================
1171 ===============================================================================
1174 #define MSG_BROADCAST 0 // unreliable to all
1175 #define MSG_ONE 1 // reliable to one (msg_entity)
1176 #define MSG_ALL 2 // reliable to all
1177 #define MSG_INIT 3 // write to the init string
1178 #define MSG_ENTITY 5
1180 sizebuf_t *WriteDest (void)
1185 extern sizebuf_t *sv2csqcbuf;
1187 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1191 return &sv.datagram;
1194 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1195 entnum = PRVM_NUM_FOR_EDICT(ent);
1196 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1198 Con_Printf ("WriteDest: tried to write to non-client\n");
1199 return &sv.reliable_datagram;
1202 return &svs.clients[entnum-1].netconnection->message;
1205 Con_Printf ("WriteDest: bad destination\n");
1207 return &sv.reliable_datagram;
1219 void PF_WriteByte (void)
1221 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1224 void PF_WriteChar (void)
1226 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1229 void PF_WriteShort (void)
1231 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1234 void PF_WriteLong (void)
1236 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1239 void PF_WriteAngle (void)
1241 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1244 void PF_WriteCoord (void)
1246 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1249 void PF_WriteString (void)
1251 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1254 void PF_WriteUnterminatedString (void)
1256 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1260 void PF_WriteEntity (void)
1262 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1265 //////////////////////////////////////////////////////////
1267 void PF_makestatic (void)
1272 ent = PRVM_G_EDICT(OFS_PARM0);
1273 if (ent == prog->edicts)
1274 PF_WARNING("makestatic: can not modify world entity\n");
1275 if (ent->priv.server->free)
1276 PF_WARNING("makestatic: can not modify free entity\n");
1279 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1284 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1285 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1286 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1290 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1291 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1292 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1295 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1296 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1297 for (i=0 ; i<3 ; i++)
1299 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1300 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1303 // throw the entity away now
1307 //=============================================================================
1314 void PF_setspawnparms (void)
1320 ent = PRVM_G_EDICT(OFS_PARM0);
1321 i = PRVM_NUM_FOR_EDICT(ent);
1322 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1324 Con_Print("tried to setspawnparms on a non-client\n");
1328 // copy spawn parms out of the client_t
1329 client = svs.clients + i-1;
1330 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1331 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1338 Returns a color vector indicating the lighting at the requested point.
1340 (Internal Operation note: actually measures the light beneath the point, just like
1341 the model lighting on the client)
1346 void PF_getlight (void)
1348 vec3_t ambientcolor, diffusecolor, diffusenormal;
1350 p = PRVM_G_VECTOR(OFS_PARM0);
1351 VectorClear(ambientcolor);
1352 VectorClear(diffusecolor);
1353 VectorClear(diffusenormal);
1354 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1355 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1356 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1359 void PF_registercvar (void)
1361 const char *name, *value;
1362 name = PRVM_G_STRING(OFS_PARM0);
1363 value = PRVM_G_STRING(OFS_PARM1);
1364 PRVM_G_FLOAT(OFS_RETURN) = 0;
1366 // first check to see if it has already been defined
1367 if (Cvar_FindVar (name))
1370 // check for overlap with a command
1371 if (Cmd_Exists (name))
1373 Con_Printf("PF_registercvar: %s is a command\n", name);
1377 Cvar_Get(name, value, 0);
1379 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1384 unsigned char type; // 1/2/8 or other value if isn't used
1388 static autosentstat_t *vm_autosentstats = NULL; //[515]: it starts from 0, not 32
1389 static int vm_autosentstats_last;
1391 void VM_AutoSentStats_Clear (void)
1393 if(vm_autosentstats)
1395 Z_Free(vm_autosentstats);
1396 vm_autosentstats = NULL;
1397 vm_autosentstats_last = -1;
1401 //[515]: add check if even bigger ? "try to use two stats, cause it's too big" ?
1402 #define VM_SENDSTAT(a,b,c)\
1405 if((c)==(unsigned char)(c))\
1407 MSG_WriteByte((a), svc_updatestatubyte);\
1408 MSG_WriteByte((a), (b));\
1409 MSG_WriteByte((a), (c));\
1413 MSG_WriteByte((a), svc_updatestat);\
1414 MSG_WriteByte((a), (b));\
1415 MSG_WriteLong((a), (c));\
1419 void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1431 if(!vm_autosentstats)
1434 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);
1436 for(i=0; i<vm_autosentstats_last+1 ;i++)
1438 if(!vm_autosentstats[i].type)
1440 switch(vm_autosentstats[i].type)
1444 t = PRVM_E_STRING(ent, vm_autosentstats[i].fieldoffset);
1452 stats[i+32] = si[0];
1453 stats[i+33] = si[1];
1454 stats[i+34] = si[2];
1455 stats[i+35] = si[3];
1459 VM_SENDSTAT(msg, i+32, si[0]);
1460 VM_SENDSTAT(msg, i+33, si[1]);
1461 VM_SENDSTAT(msg, i+34, si[2]);
1462 VM_SENDSTAT(msg, i+35, si[3]);
1468 k.f = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1469 k.i = LittleLong (k.i);
1473 VM_SENDSTAT(msg, i+32, k.i);
1477 v = (int)PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1481 VM_SENDSTAT(msg, i+32, v);
1489 // void(float index, float type, .void field) SV_AddStat = #470;
1490 // Set up an auto-sent player stat.
1491 // Client's get thier own fields sent to them. Index may not be less than 32.
1492 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1493 // 1: string (4 stats carrying a total of 16 charactures)
1494 // 2: float (one stat, float converted to an integer for transportation)
1495 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1496 void PF_SV_AddStat (void)
1501 if(!vm_autosentstats)
1503 vm_autosentstats = (autosentstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(autosentstat_t));
1504 if(!vm_autosentstats)
1506 Con_Printf("PF_SV_AddStat: not enough memory\n");
1510 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1511 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1512 off = PRVM_G_INT (OFS_PARM2);
1517 Con_Printf("PF_SV_AddStat: index may not be less than 32\n");
1520 if(i >= (MAX_CL_STATS-32))
1522 Con_Printf("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1525 if(i > (MAX_CL_STATS-32-4) && type == 1)
1527 Con_Printf("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1530 vm_autosentstats[i].type = type;
1531 vm_autosentstats[i].fieldoffset = off;
1532 if(vm_autosentstats_last < i)
1533 vm_autosentstats_last = i;
1540 copies data from one entity to another
1542 copyentity(src, dst)
1545 void PF_copyentity (void)
1547 prvm_edict_t *in, *out;
1548 in = PRVM_G_EDICT(OFS_PARM0);
1549 if (in == prog->edicts)
1550 PF_WARNING("copyentity: can not read world entity\n");
1551 if (in->priv.server->free)
1552 PF_WARNING("copyentity: can not read free entity\n");
1553 out = PRVM_G_EDICT(OFS_PARM1);
1554 if (out == prog->edicts)
1555 PF_WARNING("copyentity: can not modify world entity\n");
1556 if (out->priv.server->free)
1557 PF_WARNING("copyentity: can not modify free entity\n");
1558 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1566 sets the color of a client and broadcasts the update to all connected clients
1568 setcolor(clientent, value)
1571 void PF_setcolor (void)
1577 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1578 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1580 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1582 Con_Print("tried to setcolor a non-client\n");
1586 client = svs.clients + entnum-1;
1589 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1591 client->edict->fields.server->team = (i & 15) + 1;
1594 if (client->old_colors != client->colors)
1596 client->old_colors = client->colors;
1597 // send notification to all clients
1598 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1599 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1600 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1608 effect(origin, modelname, startframe, framecount, framerate)
1611 void PF_effect (void)
1615 s = PRVM_G_STRING(OFS_PARM1);
1617 PF_WARNING("effect: no model specified\n");
1619 i = SV_ModelIndex(s, 1);
1621 PF_WARNING("effect: model not precached\n");
1622 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));
1625 void PF_te_blood (void)
1627 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1629 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1630 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1632 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1633 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1634 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1636 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1637 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1638 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1640 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1643 void PF_te_bloodshower (void)
1645 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1647 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1648 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1650 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1651 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1652 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1654 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1655 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1656 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1658 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1660 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1663 void PF_te_explosionrgb (void)
1665 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1666 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1668 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1669 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1670 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1672 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1673 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1674 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1677 void PF_te_particlecube (void)
1679 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1681 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1682 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1684 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1685 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1686 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1688 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1689 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1690 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1692 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1693 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1694 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1696 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1698 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1699 // gravity true/false
1700 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1702 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1705 void PF_te_particlerain (void)
1707 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1709 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1710 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1712 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1713 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1714 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1716 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1717 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1718 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1720 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1721 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1722 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1724 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1726 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1729 void PF_te_particlesnow (void)
1731 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1733 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1734 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1736 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1737 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1738 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1740 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1741 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1742 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1744 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1745 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1746 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1748 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1750 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1753 void PF_te_spark (void)
1755 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1757 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1758 MSG_WriteByte(&sv.datagram, TE_SPARK);
1760 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1761 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1762 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1764 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1765 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1766 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1768 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1771 void PF_te_gunshotquad (void)
1773 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1774 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1776 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1777 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1778 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1781 void PF_te_spikequad (void)
1783 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1784 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1786 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1787 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1788 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1791 void PF_te_superspikequad (void)
1793 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1794 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1796 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1797 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1798 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1801 void PF_te_explosionquad (void)
1803 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1804 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1808 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1811 void PF_te_smallflash (void)
1813 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1814 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1816 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1817 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1818 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1821 void PF_te_customflash (void)
1823 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1825 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1826 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1828 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1830 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1832 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1834 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1836 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1837 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1838 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1841 void PF_te_gunshot (void)
1843 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1844 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1847 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1848 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1851 void PF_te_spike (void)
1853 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1854 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1856 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1857 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1858 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1861 void PF_te_superspike (void)
1863 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1864 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
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_explosion (void)
1873 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1874 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
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_tarexplosion (void)
1883 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1884 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
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_wizspike (void)
1893 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1894 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
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_knightspike (void)
1903 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1904 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
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_lavasplash (void)
1913 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1914 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1916 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1917 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1918 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1921 void PF_te_teleport (void)
1923 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1924 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1926 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1931 void PF_te_explosion2 (void)
1933 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1934 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
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);
1940 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
1941 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
1944 void PF_te_lightning1 (void)
1946 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1947 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
1949 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1952 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1953 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1955 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1960 void PF_te_lightning2 (void)
1962 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1963 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
1965 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1972 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1973 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1976 void PF_te_lightning3 (void)
1978 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1979 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
1981 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1983 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1984 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1985 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1989 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1992 void PF_te_beam (void)
1994 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1995 MSG_WriteByte(&sv.datagram, TE_BEAM);
1997 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1999 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2000 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2001 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2004 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2005 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2008 void PF_te_plasmaburn (void)
2010 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2011 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2012 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2014 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2017 void PF_te_flamejet (void)
2019 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2020 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2022 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2023 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2024 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2026 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2028 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2030 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2033 void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2036 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2038 bestdist = 1000000000;
2040 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2042 // clip original point to each triangle of the surface and find the
2043 // triangle that is closest
2044 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2045 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2046 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2047 TriangleNormal(v[0], v[1], v[2], facenormal);
2048 VectorNormalize(facenormal);
2049 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2050 VectorMA(p, offsetdist, facenormal, temp);
2051 for (j = 0, k = 2;j < 3;k = j, j++)
2053 VectorSubtract(v[k], v[j], edgenormal);
2054 CrossProduct(edgenormal, facenormal, sidenormal);
2055 VectorNormalize(sidenormal);
2056 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2058 VectorMA(temp, offsetdist, sidenormal, temp);
2060 dist = VectorDistance2(temp, p);
2061 if (bestdist > dist)
2064 VectorCopy(temp, out);
2069 static model_t *getmodel(prvm_edict_t *ed)
2072 if (!ed || ed->priv.server->free)
2074 modelindex = (int)ed->fields.server->modelindex;
2075 if (modelindex < 1 || modelindex >= MAX_MODELS)
2077 return sv.models[modelindex];
2080 static msurface_t *getsurface(model_t *model, int surfacenum)
2082 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2084 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2088 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2089 void PF_getsurfacenumpoints(void)
2092 msurface_t *surface;
2093 // return 0 if no such surface
2094 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2096 PRVM_G_FLOAT(OFS_RETURN) = 0;
2100 // note: this (incorrectly) assumes it is a simple polygon
2101 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2103 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2104 void PF_getsurfacepoint(void)
2108 msurface_t *surface;
2110 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2111 ed = PRVM_G_EDICT(OFS_PARM0);
2112 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2114 // note: this (incorrectly) assumes it is a simple polygon
2115 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2116 if (pointnum < 0 || pointnum >= surface->num_vertices)
2118 // FIXME: implement rotation/scaling
2119 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2121 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2122 void PF_getsurfacenormal(void)
2125 msurface_t *surface;
2127 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2128 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2130 // FIXME: implement rotation/scaling
2131 // note: this (incorrectly) assumes it is a simple polygon
2132 // note: this only returns the first triangle, so it doesn't work very
2133 // well for curved surfaces or arbitrary meshes
2134 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);
2135 VectorNormalize(normal);
2136 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2138 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2139 void PF_getsurfacetexture(void)
2142 msurface_t *surface;
2143 PRVM_G_INT(OFS_RETURN) = 0;
2144 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2146 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
2148 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2149 void PF_getsurfacenearpoint(void)
2151 int surfacenum, best;
2153 vec_t dist, bestdist;
2156 msurface_t *surface;
2158 PRVM_G_FLOAT(OFS_RETURN) = -1;
2159 ed = PRVM_G_EDICT(OFS_PARM0);
2160 point = PRVM_G_VECTOR(OFS_PARM1);
2162 if (!ed || ed->priv.server->free)
2164 model = getmodel(ed);
2165 if (!model || !model->num_surfaces)
2168 // FIXME: implement rotation/scaling
2169 VectorSubtract(point, ed->fields.server->origin, p);
2171 bestdist = 1000000000;
2172 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2174 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2175 // first see if the nearest point on the surface's box is closer than the previous match
2176 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2177 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2178 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2179 dist = VectorLength2(clipped);
2180 if (dist < bestdist)
2182 // it is, check the nearest point on the actual geometry
2183 clippointtosurface(model, surface, p, clipped);
2184 VectorSubtract(clipped, p, clipped);
2185 dist += VectorLength2(clipped);
2186 if (dist < bestdist)
2188 // that's closer too, store it as the best match
2194 PRVM_G_FLOAT(OFS_RETURN) = best;
2196 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2197 void PF_getsurfaceclippedpoint(void)
2201 msurface_t *surface;
2203 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2204 ed = PRVM_G_EDICT(OFS_PARM0);
2205 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2207 // FIXME: implement rotation/scaling
2208 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2209 clippointtosurface(model, surface, p, out);
2210 // FIXME: implement rotation/scaling
2211 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2214 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2215 //this function originally written by KrimZon, made shorter by LordHavoc
2216 void PF_clientcommand (void)
2218 client_t *temp_client;
2221 //find client for this entity
2222 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2223 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2225 Con_Print("PF_clientcommand: entity is not a client\n");
2229 temp_client = host_client;
2230 host_client = svs.clients + i;
2231 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2232 host_client = temp_client;
2235 //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)
2236 void PF_setattachment (void)
2238 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2239 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2240 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2245 if (e == prog->edicts)
2246 PF_WARNING("setattachment: can not modify world entity\n");
2247 if (e->priv.server->free)
2248 PF_WARNING("setattachment: can not modify free entity\n");
2250 if (tagentity == NULL)
2251 tagentity = prog->edicts;
2253 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2255 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2257 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2260 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2262 modelindex = (int)tagentity->fields.server->modelindex;
2263 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2265 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2267 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);
2270 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));
2274 /////////////////////////////////////////
2275 // DP_MD3_TAGINFO extension coded by VorteX
2277 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2282 i = (int)e->fields.server->modelindex;
2283 if (i < 1 || i >= MAX_MODELS)
2285 model = sv.models[i];
2287 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2290 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2292 float scale = PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float;
2296 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);
2298 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 * 0.333);
2301 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2307 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2308 && (model = sv.models[(int)ent->fields.server->modelindex])
2309 && model->animscenes)
2311 // if model has wrong frame, engine automatically switches to model first frame
2312 frame = (int)ent->fields.server->frame;
2313 if (frame < 0 || frame >= model->numframes)
2315 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2317 *out = identitymatrix;
2321 // Warnings/errors code:
2322 // 0 - normal (everything all-right)
2325 // 3 - null or non-precached model
2326 // 4 - no tags with requested index
2327 // 5 - runaway loop at attachment chain
2328 extern cvar_t cl_bob;
2329 extern cvar_t cl_bobcycle;
2330 extern cvar_t cl_bobup;
2331 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2335 int modelindex, attachloop;
2336 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2339 *out = identitymatrix; // warnings and errors return identical matrix
2341 if (ent == prog->edicts)
2343 if (ent->priv.server->free)
2346 modelindex = (int)ent->fields.server->modelindex;
2347 if (modelindex <= 0 || modelindex > MAX_MODELS)
2350 model = sv.models[modelindex];
2352 tagmatrix = identitymatrix;
2353 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2357 if (attachloop >= 256) // prevent runaway looping
2359 // apply transformation by child's tagindex on parent entity and then
2360 // by parent entity itself
2361 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2362 if (ret && attachloop == 0)
2364 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2365 SV_GetEntityMatrix(ent, &entitymatrix, false);
2366 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2367 // next iteration we process the parent entity
2368 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2370 tagindex = (int)PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
2371 ent = PRVM_EDICT_NUM(val->edict);
2378 // RENDER_VIEWMODEL magic
2379 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2381 Matrix4x4_Copy(&tagmatrix, out);
2382 ent = PRVM_EDICT_NUM(val->edict);
2384 SV_GetEntityMatrix(ent, &entitymatrix, true);
2385 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2388 // Cl_bob, ported from rendering code
2389 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2392 // LordHavoc: this code is *weird*, but not replacable (I think it
2393 // should be done in QC on the server, but oh well, quake is quake)
2394 // LordHavoc: figured out bobup: the time at which the sin is at 180
2395 // degrees (which allows lengthening or squishing the peak or valley)
2396 cycle = sv.time/cl_bobcycle.value;
2397 cycle -= (int)cycle;
2398 if (cycle < cl_bobup.value)
2399 cycle = sin(M_PI * cycle / cl_bobup.value);
2401 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2402 // bob is proportional to velocity in the xy plane
2403 // (don't count Z, or jumping messes it up)
2404 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;
2405 bob = bob*0.3 + bob*0.7*cycle;
2406 out->m[2][3] += bound(-7, bob, 4);
2413 //float(entity ent, string tagname) gettagindex;
2415 void PF_gettagindex (void)
2417 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2418 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2419 int modelindex, tag_index;
2421 if (ent == prog->edicts)
2422 PF_WARNING("gettagindex: can't affect world entity\n");
2423 if (ent->priv.server->free)
2424 PF_WARNING("gettagindex: can't affect free entity\n");
2426 modelindex = (int)ent->fields.server->modelindex;
2428 if (modelindex <= 0 || modelindex > MAX_MODELS)
2429 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2432 tag_index = SV_GetTagIndex(ent, tag_name);
2434 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2436 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2439 //vector(entity ent, float tagindex) gettaginfo;
2440 void PF_gettaginfo (void)
2442 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2443 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2444 matrix4x4_t tag_matrix;
2447 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2448 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2453 PF_WARNING("gettagindex: can't affect world entity\n");
2456 PF_WARNING("gettagindex: can't affect free entity\n");
2459 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2462 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2465 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2470 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2471 void PF_dropclient (void)
2474 client_t *oldhostclient;
2475 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2476 if (clientnum < 0 || clientnum >= svs.maxclients)
2477 PF_WARNING("dropclient: not a client\n");
2478 if (!svs.clients[clientnum].active)
2479 PF_WARNING("dropclient: that client slot is not connected\n");
2480 oldhostclient = host_client;
2481 host_client = svs.clients + clientnum;
2482 SV_DropClient(false);
2483 host_client = oldhostclient;
2486 //entity() spawnclient (DP_SV_BOTCLIENT)
2487 void PF_spawnclient (void)
2491 prog->xfunction->builtinsprofile += 2;
2493 for (i = 0;i < svs.maxclients;i++)
2495 if (!svs.clients[i].active)
2497 prog->xfunction->builtinsprofile += 100;
2498 SV_ConnectClient (i, NULL);
2499 // this has to be set or else ClientDisconnect won't be called
2500 // we assume the qc will call ClientConnect...
2501 svs.clients[i].clientconnectcalled = true;
2502 ed = PRVM_EDICT_NUM(i + 1);
2506 VM_RETURN_EDICT(ed);
2509 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2510 void PF_clienttype (void)
2513 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2514 if (clientnum < 0 || clientnum >= svs.maxclients)
2515 PRVM_G_FLOAT(OFS_RETURN) = 3;
2516 else if (!svs.clients[clientnum].active)
2517 PRVM_G_FLOAT(OFS_RETURN) = 0;
2518 else if (svs.clients[clientnum].netconnection)
2519 PRVM_G_FLOAT(OFS_RETURN) = 1;
2521 PRVM_G_FLOAT(OFS_RETURN) = 2;
2524 void PF_edict_num (void)
2526 VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0)));
2529 prvm_builtin_t vm_sv_builtins[] = {
2531 PF_makevectors, // #1 void(vector ang) makevectors
2532 PF_setorigin, // #2 void(entity e, vector o) setorigin
2533 PF_setmodel, // #3 void(entity e, string m) setmodel
2534 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2535 NULL, // #5 void(entity e, vector min, vector max) setabssize
2536 VM_break, // #6 void() break
2537 VM_random, // #7 float() random
2538 PF_sound, // #8 void(entity e, float chan, string samp) sound
2539 VM_normalize, // #9 vector(vector v) normalize
2540 VM_error, // #10 void(string e) error
2541 VM_objerror, // #11 void(string e) objerror
2542 VM_vlen, // #12 float(vector v) vlen
2543 VM_vectoyaw, // #13 float(vector v) vectoyaw
2544 VM_spawn, // #14 entity() spawn
2545 VM_remove, // #15 void(entity e) remove
2546 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2547 PF_checkclient, // #17 entity() clientlist
2548 VM_find, // #18 entity(entity start, .string fld, string match) find
2549 PF_precache_sound, // #19 void(string s) precache_sound
2550 PF_precache_model, // #20 void(string s) precache_model
2551 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2552 PF_findradius, // #22 entity(vector org, float rad) findradius
2553 VM_bprint, // #23 void(string s) bprint
2554 PF_sprint, // #24 void(entity client, string s) sprint
2555 VM_dprint, // #25 void(string s) dprint
2556 VM_ftos, // #26 void(string s) ftos
2557 VM_vtos, // #27 void(string s) vtos
2558 VM_coredump, // #28 void() coredump
2559 VM_traceon, // #29 void() traceon
2560 VM_traceoff, // #30 void() traceoff
2561 VM_eprint, // #31 void(entity e) eprint
2562 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2564 PF_droptofloor, // #34 float() droptofloor
2565 PF_lightstyle, // #35 void(float style, string value) lightstyle
2566 VM_rint, // #36 float(float v) rint
2567 VM_floor, // #37 float(float v) floor
2568 VM_ceil, // #38 float(float v) ceil
2570 PF_checkbottom, // #40 float(entity e) checkbottom
2571 PF_pointcontents, // #41 float(vector v) pointcontents
2573 VM_fabs, // #43 float(float f) fabs
2574 PF_aim, // #44 vector(entity e, float speed) aim
2575 VM_cvar, // #45 float(string s) cvar
2576 VM_localcmd, // #46 void(string s) localcmd
2577 VM_nextent, // #47 entity(entity e) nextent
2578 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2579 PF_changeyaw, // #49 void() ChangeYaw
2581 VM_vectoangles, // #51 vector(vector v) vectoangles
2582 PF_WriteByte, // #52 void(float to, float f) WriteByte
2583 PF_WriteChar, // #53 void(float to, float f) WriteChar
2584 PF_WriteShort, // #54 void(float to, float f) WriteShort
2585 PF_WriteLong, // #55 void(float to, float f) WriteLong
2586 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2587 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2588 PF_WriteString, // #58 void(float to, string s) WriteString
2589 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2590 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2591 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2592 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2593 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2594 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2595 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2597 SV_MoveToGoal, // #67 void(float step) movetogoal
2598 PF_precache_file, // #68 string(string s) precache_file
2599 PF_makestatic, // #69 void(entity e) makestatic
2600 VM_changelevel, // #70 void(string s) changelevel
2602 VM_cvar_set, // #72 void(string var, string val) cvar_set
2603 PF_centerprint, // #73 void(entity client, strings) centerprint
2604 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2605 PF_precache_model, // #75 string(string s) precache_model2
2606 PF_precache_sound, // #76 string(string s) precache_sound2
2607 PF_precache_file, // #77 string(string s) precache_file2
2608 PF_setspawnparms, // #78 void(entity e) setspawnparms
2611 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2620 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2621 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2622 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2623 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2624 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2625 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2626 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2627 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2628 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2629 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2640 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2641 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2642 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2643 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2644 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2645 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2646 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2647 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2648 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2649 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2650 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2651 // FTEQW range #200-#299
2670 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2680 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2681 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2682 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2683 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2684 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2685 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2686 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2687 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2688 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2689 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2690 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2691 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2692 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2693 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2694 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2695 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2696 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2697 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2698 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2699 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2700 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2701 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2702 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2703 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2704 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2705 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2706 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2707 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2708 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2709 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2710 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2711 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2712 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2713 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2714 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2715 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2716 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2717 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2718 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2719 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2720 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2721 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2722 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2723 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2724 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2725 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2726 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2727 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2728 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2729 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2730 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2731 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2732 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2733 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2734 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2735 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2736 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2737 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2738 PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2740 PF_edict_num, // #459 entity(float num) (??)
2741 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2742 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2743 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2744 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2745 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2746 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2747 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2748 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2749 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2750 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2751 PF_SV_AddStat, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2761 e10, e10 // #480-499 (LordHavoc)
2764 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2766 void VM_SV_Cmd_Init(void)
2771 void VM_SV_Cmd_Reset(void)