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)
264 PF_WARNING("tried to centerprint to a non-client\n");
266 client = svs.clients + entnum-1;
267 if (!client->netconnection)
270 VM_VarString(1, string, sizeof(string));
271 MSG_WriteChar(&client->netconnection->message,svc_print);
272 MSG_WriteString(&client->netconnection->message, string);
280 single print to a specific client
282 centerprint(clientent, value)
285 void PF_centerprint (void)
289 char string[VM_STRINGTEMP_LENGTH];
291 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
293 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
294 PF_WARNING("tried to centerprint to a non-client\n");
296 client = svs.clients + entnum-1;
297 if (!client->netconnection)
300 VM_VarString(1, string, sizeof(string));
301 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
302 MSG_WriteString(&client->netconnection->message, string);
309 particle(origin, color, count)
312 void PF_particle (void)
318 org = PRVM_G_VECTOR(OFS_PARM0);
319 dir = PRVM_G_VECTOR(OFS_PARM1);
320 color = PRVM_G_FLOAT(OFS_PARM2);
321 count = PRVM_G_FLOAT(OFS_PARM3);
322 SV_StartParticle (org, dir, (int)color, (int)count);
332 void PF_ambientsound (void)
336 float vol, attenuation;
339 pos = PRVM_G_VECTOR (OFS_PARM0);
340 samp = PRVM_G_STRING(OFS_PARM1);
341 vol = PRVM_G_FLOAT(OFS_PARM2);
342 attenuation = PRVM_G_FLOAT(OFS_PARM3);
344 // check to see if samp was properly precached
345 soundnum = SV_SoundIndex(samp, 1);
353 // add an svc_spawnambient command to the level signon packet
356 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
358 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
360 MSG_WriteVector(&sv.signon, pos, sv.protocol);
363 MSG_WriteShort (&sv.signon, soundnum);
365 MSG_WriteByte (&sv.signon, soundnum);
367 MSG_WriteByte (&sv.signon, (int)(vol*255));
368 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
376 Each entity can have eight independant sound sources, like voice,
379 Channel 0 is an auto-allocate channel, the others override anything
380 already running on that entity/channel pair.
382 An attenuation of 0 will play full volume everywhere in the level.
383 Larger attenuations will drop off.
391 prvm_edict_t *entity;
395 entity = PRVM_G_EDICT(OFS_PARM0);
396 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
397 sample = PRVM_G_STRING(OFS_PARM2);
398 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
399 attenuation = PRVM_G_FLOAT(OFS_PARM4);
401 if (volume < 0 || volume > 255)
402 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
404 if (attenuation < 0 || attenuation > 4)
405 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
407 if (channel < 0 || channel > 7)
408 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
410 SV_StartSound (entity, channel, sample, volume, attenuation);
417 Used for use tracing and shot targeting
418 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
419 if the tryents flag is set.
421 traceline (vector1, vector2, tryents)
424 void PF_traceline (void)
432 prog->xfunction->builtinsprofile += 30;
434 v1 = PRVM_G_VECTOR(OFS_PARM0);
435 v2 = PRVM_G_VECTOR(OFS_PARM1);
436 move = (int)PRVM_G_FLOAT(OFS_PARM2);
437 ent = PRVM_G_EDICT(OFS_PARM3);
439 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]))
440 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));
442 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
444 prog->globals.server->trace_allsolid = trace.allsolid;
445 prog->globals.server->trace_startsolid = trace.startsolid;
446 prog->globals.server->trace_fraction = trace.fraction;
447 prog->globals.server->trace_inwater = trace.inwater;
448 prog->globals.server->trace_inopen = trace.inopen;
449 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
450 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
451 prog->globals.server->trace_plane_dist = trace.plane.dist;
453 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
455 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
456 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
457 val->_float = trace.startsupercontents;
458 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
459 val->_float = trace.hitsupercontents;
460 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
461 val->_float = trace.hitq3surfaceflags;
462 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
464 if (trace.hittexture)
466 char *s = VM_GetTempString();
467 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
468 val->string = PRVM_SetEngineString(s);
480 Used for use tracing and shot targeting
481 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
482 if the tryents flag is set.
484 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
487 // LordHavoc: added this for my own use, VERY useful, similar to traceline
488 void PF_tracebox (void)
490 float *v1, *v2, *m1, *m2;
496 prog->xfunction->builtinsprofile += 30;
498 v1 = PRVM_G_VECTOR(OFS_PARM0);
499 m1 = PRVM_G_VECTOR(OFS_PARM1);
500 m2 = PRVM_G_VECTOR(OFS_PARM2);
501 v2 = PRVM_G_VECTOR(OFS_PARM3);
502 move = (int)PRVM_G_FLOAT(OFS_PARM4);
503 ent = PRVM_G_EDICT(OFS_PARM5);
505 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]))
506 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));
508 trace = SV_Move (v1, m1, m2, v2, move, ent);
510 prog->globals.server->trace_allsolid = trace.allsolid;
511 prog->globals.server->trace_startsolid = trace.startsolid;
512 prog->globals.server->trace_fraction = trace.fraction;
513 prog->globals.server->trace_inwater = trace.inwater;
514 prog->globals.server->trace_inopen = trace.inopen;
515 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
516 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
517 prog->globals.server->trace_plane_dist = trace.plane.dist;
519 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
521 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
522 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
523 val->_float = trace.startsupercontents;
524 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
525 val->_float = trace.hitsupercontents;
526 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
527 val->_float = trace.hitq3surfaceflags;
528 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
530 if (trace.hittexture)
532 char *s = VM_GetTempString();
533 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
534 val->string = PRVM_SetEngineString(s);
541 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
542 void PF_tracetoss (void)
546 prvm_edict_t *ignore;
549 prog->xfunction->builtinsprofile += 600;
551 ent = PRVM_G_EDICT(OFS_PARM0);
552 if (ent == prog->edicts)
553 PF_WARNING("tracetoss: can not use world entity\n");
554 ignore = PRVM_G_EDICT(OFS_PARM1);
556 trace = SV_Trace_Toss (ent, ignore);
558 prog->globals.server->trace_allsolid = trace.allsolid;
559 prog->globals.server->trace_startsolid = trace.startsolid;
560 prog->globals.server->trace_fraction = trace.fraction;
561 prog->globals.server->trace_inwater = trace.inwater;
562 prog->globals.server->trace_inopen = trace.inopen;
563 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
564 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
565 prog->globals.server->trace_plane_dist = trace.plane.dist;
567 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
569 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
570 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
571 val->_float = trace.startsupercontents;
572 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
573 val->_float = trace.hitsupercontents;
574 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
575 val->_float = trace.hitq3surfaceflags;
576 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
578 if (trace.hittexture)
580 char *s = VM_GetTempString();
581 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
582 val->string = PRVM_SetEngineString(s);
594 Returns true if the given entity can move to the given position from it's
595 current position by walking or rolling.
597 scalar checkpos (entity, vector)
600 void PF_checkpos (void)
604 //============================================================================
607 unsigned char checkpvs[MAX_MAP_LEAFS/8];
609 int PF_newcheckclient (int check)
615 // cycle to the next one
617 check = bound(1, check, svs.maxclients);
618 if (check == svs.maxclients)
626 prog->xfunction->builtinsprofile++;
628 if (i == svs.maxclients+1)
630 // look up the client's edict
631 ent = PRVM_EDICT_NUM(i);
632 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
633 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
635 // found a valid client (possibly the same one again)
639 // get the PVS for the entity
640 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
642 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
643 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
652 Returns a client (or object that has a client enemy) that would be a
655 If there is more than one valid option, they are cycled each frame
657 If (self.origin + self.viewofs) is not in the PVS of the current target,
658 it is not returned at all.
663 int c_invis, c_notvis;
664 void PF_checkclient (void)
666 prvm_edict_t *ent, *self;
669 // find a new check if on a new frame
670 if (sv.time - sv.lastchecktime >= 0.1)
672 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
673 sv.lastchecktime = sv.time;
676 // return check if it might be visible
677 ent = PRVM_EDICT_NUM(sv.lastcheck);
678 if (ent->priv.server->free || ent->fields.server->health <= 0)
680 VM_RETURN_EDICT(prog->edicts);
684 // if current entity can't possibly see the check entity, return 0
685 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
686 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
687 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
690 VM_RETURN_EDICT(prog->edicts);
694 // might be able to see it
696 VM_RETURN_EDICT(ent);
699 //============================================================================
706 Sends text over to the client's execution buffer
708 stuffcmd (clientent, value, ...)
711 void PF_stuffcmd (void)
715 char string[VM_STRINGTEMP_LENGTH];
717 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
718 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
719 PF_WARNING("Can't stuffcmd to a non-client\n");
721 VM_VarString(1, string, sizeof(string));
724 host_client = svs.clients + entnum-1;
725 Host_ClientCommands ("%s", string);
733 Returns a chain of entities that have origins within a spherical area
735 findradius (origin, radius)
738 void PF_findradius (void)
740 prvm_edict_t *ent, *chain;
741 vec_t radius, radius2;
742 vec3_t org, eorg, mins, maxs;
745 prvm_edict_t *touchedicts[MAX_EDICTS];
747 chain = (prvm_edict_t *)prog->edicts;
749 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
750 radius = PRVM_G_FLOAT(OFS_PARM1);
751 radius2 = radius * radius;
753 mins[0] = org[0] - (radius + 1);
754 mins[1] = org[1] - (radius + 1);
755 mins[2] = org[2] - (radius + 1);
756 maxs[0] = org[0] + (radius + 1);
757 maxs[1] = org[1] + (radius + 1);
758 maxs[2] = org[2] + (radius + 1);
759 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
760 if (numtouchedicts > MAX_EDICTS)
762 // this never happens
763 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
764 numtouchedicts = MAX_EDICTS;
766 for (i = 0;i < numtouchedicts;i++)
768 ent = touchedicts[i];
769 prog->xfunction->builtinsprofile++;
770 // Quake did not return non-solid entities but darkplaces does
771 // (note: this is the reason you can't blow up fallen zombies)
772 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
774 // LordHavoc: compare against bounding box rather than center so it
775 // doesn't miss large objects, and use DotProduct instead of Length
776 // for a major speedup
777 VectorSubtract(org, ent->fields.server->origin, eorg);
778 if (sv_gameplayfix_findradiusdistancetobox.integer)
780 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
781 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
782 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
785 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
786 if (DotProduct(eorg, eorg) < radius2)
788 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
793 VM_RETURN_EDICT(chain);
796 void PF_precache_file (void)
797 { // precache_file is only used to copy files with qcc, it does nothing
798 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
802 void PF_precache_sound (void)
804 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
805 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
808 void PF_precache_model (void)
810 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
811 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
818 float(float yaw, float dist) walkmove
821 void PF_walkmove (void)
829 // assume failure if it returns early
830 PRVM_G_FLOAT(OFS_RETURN) = 0;
832 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
833 if (ent == prog->edicts)
834 PF_WARNING("walkmove: can not modify world entity\n");
835 if (ent->priv.server->free)
836 PF_WARNING("walkmove: can not modify free entity\n");
837 yaw = PRVM_G_FLOAT(OFS_PARM0);
838 dist = PRVM_G_FLOAT(OFS_PARM1);
840 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
843 yaw = yaw*M_PI*2 / 360;
845 move[0] = cos(yaw)*dist;
846 move[1] = sin(yaw)*dist;
849 // save program state, because SV_movestep may call other progs
850 oldf = prog->xfunction;
851 oldself = prog->globals.server->self;
853 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
856 // restore program state
857 prog->xfunction = oldf;
858 prog->globals.server->self = oldself;
868 void PF_droptofloor (void)
874 // assume failure if it returns early
875 PRVM_G_FLOAT(OFS_RETURN) = 0;
877 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
878 if (ent == prog->edicts)
879 PF_WARNING("droptofloor: can not modify world entity\n");
880 if (ent->priv.server->free)
881 PF_WARNING("droptofloor: can not modify free entity\n");
883 VectorCopy (ent->fields.server->origin, end);
886 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
888 if (trace.fraction != 1)
890 VectorCopy (trace.endpos, ent->fields.server->origin);
891 SV_LinkEdict (ent, false);
892 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
893 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
894 PRVM_G_FLOAT(OFS_RETURN) = 1;
895 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
896 ent->priv.server->suspendedinairflag = true;
904 void(float style, string value) lightstyle
907 void PF_lightstyle (void)
914 style = (int)PRVM_G_FLOAT(OFS_PARM0);
915 val = PRVM_G_STRING(OFS_PARM1);
917 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
918 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
921 // change the string in sv
922 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
924 // send message to all clients on this server
925 if (sv.state != ss_active)
928 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
930 if (client->active && client->netconnection)
932 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
933 MSG_WriteChar (&client->netconnection->message,style);
934 MSG_WriteString (&client->netconnection->message, val);
944 void PF_checkbottom (void)
946 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
954 void PF_pointcontents (void)
956 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
963 Pick a vector for the player to shoot along
964 vector aim(entity, missilespeed)
969 prvm_edict_t *ent, *check, *bestent;
970 vec3_t start, dir, end, bestdir;
973 float dist, bestdist;
976 // assume failure if it returns early
977 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
978 // if sv_aim is so high it can't possibly accept anything, skip out early
979 if (sv_aim.value >= 1)
982 ent = PRVM_G_EDICT(OFS_PARM0);
983 if (ent == prog->edicts)
984 PF_WARNING("aim: can not use world entity\n");
985 if (ent->priv.server->free)
986 PF_WARNING("aim: can not use free entity\n");
987 speed = PRVM_G_FLOAT(OFS_PARM1);
989 VectorCopy (ent->fields.server->origin, start);
992 // try sending a trace straight
993 VectorCopy (prog->globals.server->v_forward, dir);
994 VectorMA (start, 2048, dir, end);
995 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
996 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
997 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
999 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1004 // try all possible entities
1005 VectorCopy (dir, bestdir);
1006 bestdist = sv_aim.value;
1009 check = PRVM_NEXT_EDICT(prog->edicts);
1010 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1012 prog->xfunction->builtinsprofile++;
1013 if (check->fields.server->takedamage != DAMAGE_AIM)
1017 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1018 continue; // don't aim at teammate
1019 for (j=0 ; j<3 ; j++)
1020 end[j] = check->fields.server->origin[j]
1021 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1022 VectorSubtract (end, start, dir);
1023 VectorNormalize (dir);
1024 dist = DotProduct (dir, prog->globals.server->v_forward);
1025 if (dist < bestdist)
1026 continue; // to far to turn
1027 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1028 if (tr.ent == check)
1029 { // can shoot at this one
1037 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1038 dist = DotProduct (dir, prog->globals.server->v_forward);
1039 VectorScale (prog->globals.server->v_forward, dist, end);
1041 VectorNormalize (end);
1042 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1046 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1054 This was a major timewaster in progs, so it was converted to C
1057 void PF_changeyaw (void)
1060 float ideal, current, move, speed;
1062 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1063 if (ent == prog->edicts)
1064 PF_WARNING("changeyaw: can not modify world entity\n");
1065 if (ent->priv.server->free)
1066 PF_WARNING("changeyaw: can not modify free entity\n");
1067 current = ANGLEMOD(ent->fields.server->angles[1]);
1068 ideal = ent->fields.server->ideal_yaw;
1069 speed = ent->fields.server->yaw_speed;
1071 if (current == ideal)
1073 move = ideal - current;
1074 if (ideal > current)
1095 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1103 void PF_changepitch (void)
1106 float ideal, current, move, speed;
1109 ent = PRVM_G_EDICT(OFS_PARM0);
1110 if (ent == prog->edicts)
1111 PF_WARNING("changepitch: can not modify world entity\n");
1112 if (ent->priv.server->free)
1113 PF_WARNING("changepitch: can not modify free entity\n");
1114 current = ANGLEMOD( ent->fields.server->angles[0] );
1115 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1116 ideal = val->_float;
1119 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1122 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1123 speed = val->_float;
1126 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1130 if (current == ideal)
1132 move = ideal - current;
1133 if (ideal > current)
1154 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1158 ===============================================================================
1162 ===============================================================================
1165 #define MSG_BROADCAST 0 // unreliable to all
1166 #define MSG_ONE 1 // reliable to one (msg_entity)
1167 #define MSG_ALL 2 // reliable to all
1168 #define MSG_INIT 3 // write to the init string
1169 #define MSG_ENTITY 5
1171 sizebuf_t *WriteDest (void)
1176 extern sizebuf_t *sv2csqcbuf;
1178 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1182 return &sv.datagram;
1185 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1186 entnum = PRVM_NUM_FOR_EDICT(ent);
1187 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1189 Con_Printf ("WriteDest: tried to write to non-client\n");
1190 return &sv.reliable_datagram;
1193 return &svs.clients[entnum-1].netconnection->message;
1196 Con_Printf ("WriteDest: bad destination\n");
1198 return &sv.reliable_datagram;
1210 void PF_WriteByte (void)
1212 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1215 void PF_WriteChar (void)
1217 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1220 void PF_WriteShort (void)
1222 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1225 void PF_WriteLong (void)
1227 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1230 void PF_WriteAngle (void)
1232 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1235 void PF_WriteCoord (void)
1237 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1240 void PF_WriteString (void)
1242 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1245 void PF_WriteUnterminatedString (void)
1247 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1251 void PF_WriteEntity (void)
1253 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1256 //////////////////////////////////////////////////////////
1258 void PF_makestatic (void)
1263 ent = PRVM_G_EDICT(OFS_PARM0);
1264 if (ent == prog->edicts)
1265 PF_WARNING("makestatic: can not modify world entity\n");
1266 if (ent->priv.server->free)
1267 PF_WARNING("makestatic: can not modify free entity\n");
1270 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1275 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1276 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1277 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1281 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1282 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1283 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1286 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1287 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1288 for (i=0 ; i<3 ; i++)
1290 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1291 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1294 // throw the entity away now
1298 //=============================================================================
1305 void PF_setspawnparms (void)
1311 ent = PRVM_G_EDICT(OFS_PARM0);
1312 i = PRVM_NUM_FOR_EDICT(ent);
1313 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1315 Con_Print("tried to setspawnparms on a non-client\n");
1319 // copy spawn parms out of the client_t
1320 client = svs.clients + i-1;
1321 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1322 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1329 Returns a color vector indicating the lighting at the requested point.
1331 (Internal Operation note: actually measures the light beneath the point, just like
1332 the model lighting on the client)
1337 void PF_getlight (void)
1339 vec3_t ambientcolor, diffusecolor, diffusenormal;
1341 p = PRVM_G_VECTOR(OFS_PARM0);
1342 VectorClear(ambientcolor);
1343 VectorClear(diffusecolor);
1344 VectorClear(diffusenormal);
1345 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1346 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1347 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1350 void PF_registercvar (void)
1352 const char *name, *value;
1353 name = PRVM_G_STRING(OFS_PARM0);
1354 value = PRVM_G_STRING(OFS_PARM1);
1355 PRVM_G_FLOAT(OFS_RETURN) = 0;
1357 // first check to see if it has already been defined
1358 if (Cvar_FindVar (name))
1361 // check for overlap with a command
1362 if (Cmd_Exists (name))
1364 Con_Printf("PF_registercvar: %s is a command\n", name);
1368 Cvar_Get(name, value, 0);
1370 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1375 unsigned char type; // 1/2/8 or other value if isn't used
1379 static autosentstat_t *vm_autosentstats = NULL; //[515]: it starts from 0, not 32
1380 static int vm_autosentstats_last;
1382 void VM_AutoSentStats_Clear (void)
1384 if(vm_autosentstats)
1386 Z_Free(vm_autosentstats);
1387 vm_autosentstats = NULL;
1388 vm_autosentstats_last = -1;
1392 //[515]: add check if even bigger ? "try to use two stats, cause it's too big" ?
1393 #define VM_SENDSTAT(a,b,c)\
1396 if((c)==(unsigned char)(c))\
1398 MSG_WriteByte((a), svc_updatestatubyte);\
1399 MSG_WriteByte((a), (b));\
1400 MSG_WriteByte((a), (c));\
1404 MSG_WriteByte((a), svc_updatestat);\
1405 MSG_WriteByte((a), (b));\
1406 MSG_WriteLong((a), (c));\
1410 void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1422 if(!vm_autosentstats)
1425 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);
1427 for(i=0; i<vm_autosentstats_last+1 ;i++)
1429 if(!vm_autosentstats[i].type)
1431 switch(vm_autosentstats[i].type)
1435 t = PRVM_E_STRING(ent, vm_autosentstats[i].fieldoffset);
1443 stats[i+32] = si[0];
1444 stats[i+33] = si[1];
1445 stats[i+34] = si[2];
1446 stats[i+35] = si[3];
1450 VM_SENDSTAT(msg, i+32, si[0]);
1451 VM_SENDSTAT(msg, i+33, si[1]);
1452 VM_SENDSTAT(msg, i+34, si[2]);
1453 VM_SENDSTAT(msg, i+35, si[3]);
1459 k.f = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1460 k.i = LittleLong (k.i);
1464 VM_SENDSTAT(msg, i+32, k.i);
1468 v = (int)PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1472 VM_SENDSTAT(msg, i+32, v);
1480 // void(float index, float type, .void field) SV_AddStat = #470;
1481 // Set up an auto-sent player stat.
1482 // Client's get thier own fields sent to them. Index may not be less than 32.
1483 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1484 // 1: string (4 stats carrying a total of 16 charactures)
1485 // 2: float (one stat, float converted to an integer for transportation)
1486 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1487 void PF_SV_AddStat (void)
1492 if(!vm_autosentstats)
1494 vm_autosentstats = (autosentstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(autosentstat_t));
1495 if(!vm_autosentstats)
1497 Con_Printf("PF_SV_AddStat: not enough memory\n");
1501 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1502 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1503 off = PRVM_G_INT (OFS_PARM2);
1508 Con_Printf("PF_SV_AddStat: index may not be less than 32\n");
1511 if(i >= (MAX_CL_STATS-32))
1513 Con_Printf("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1516 if(i > (MAX_CL_STATS-32-4) && type == 1)
1518 Con_Printf("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1521 vm_autosentstats[i].type = type;
1522 vm_autosentstats[i].fieldoffset = off;
1523 if(vm_autosentstats_last < i)
1524 vm_autosentstats_last = i;
1531 copies data from one entity to another
1533 copyentity(src, dst)
1536 void PF_copyentity (void)
1538 prvm_edict_t *in, *out;
1539 in = PRVM_G_EDICT(OFS_PARM0);
1540 if (in == prog->edicts)
1541 PF_WARNING("copyentity: can not read world entity\n");
1542 if (in->priv.server->free)
1543 PF_WARNING("copyentity: can not read free entity\n");
1544 out = PRVM_G_EDICT(OFS_PARM1);
1545 if (out == prog->edicts)
1546 PF_WARNING("copyentity: can not modify world entity\n");
1547 if (out->priv.server->free)
1548 PF_WARNING("copyentity: can not modify free entity\n");
1549 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1557 sets the color of a client and broadcasts the update to all connected clients
1559 setcolor(clientent, value)
1562 void PF_setcolor (void)
1568 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1569 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1571 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1573 Con_Print("tried to setcolor a non-client\n");
1577 client = svs.clients + entnum-1;
1580 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1582 client->edict->fields.server->team = (i & 15) + 1;
1585 if (client->old_colors != client->colors)
1587 client->old_colors = client->colors;
1588 // send notification to all clients
1589 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1590 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1591 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1599 effect(origin, modelname, startframe, framecount, framerate)
1602 void PF_effect (void)
1606 s = PRVM_G_STRING(OFS_PARM1);
1608 PF_WARNING("effect: no model specified\n");
1610 i = SV_ModelIndex(s, 1);
1612 PF_WARNING("effect: model not precached\n");
1613 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));
1616 void PF_te_blood (void)
1618 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1620 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1621 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1623 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1624 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1625 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1627 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1628 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1629 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1631 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1634 void PF_te_bloodshower (void)
1636 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1638 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1639 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1641 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1642 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1643 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1645 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1646 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1647 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1649 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1651 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1654 void PF_te_explosionrgb (void)
1656 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1657 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1659 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1660 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1661 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1663 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1664 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1665 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1668 void PF_te_particlecube (void)
1670 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1672 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1673 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1675 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1676 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1677 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1679 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1680 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1681 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1683 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1684 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1685 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1687 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1689 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1690 // gravity true/false
1691 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1693 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1696 void PF_te_particlerain (void)
1698 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1700 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1701 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1703 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1704 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1705 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1707 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1708 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1709 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1711 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1712 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1713 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1715 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1717 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1720 void PF_te_particlesnow (void)
1722 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1724 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1725 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1727 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1728 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1729 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1731 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1732 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1733 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1735 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1736 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1737 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1739 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1741 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1744 void PF_te_spark (void)
1746 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1748 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1749 MSG_WriteByte(&sv.datagram, TE_SPARK);
1751 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1752 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1753 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1755 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1756 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1757 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1759 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1762 void PF_te_gunshotquad (void)
1764 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1765 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1767 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1768 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1769 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1772 void PF_te_spikequad (void)
1774 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1775 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1777 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1778 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1779 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1782 void PF_te_superspikequad (void)
1784 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1785 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1787 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1788 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1789 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1792 void PF_te_explosionquad (void)
1794 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1795 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1797 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1798 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1799 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1802 void PF_te_smallflash (void)
1804 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1805 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1808 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1809 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1812 void PF_te_customflash (void)
1814 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1816 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1817 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1819 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1820 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1821 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1823 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1825 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1827 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1828 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1829 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1832 void PF_te_gunshot (void)
1834 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1835 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1837 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1838 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1839 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1842 void PF_te_spike (void)
1844 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1845 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1847 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1848 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1849 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1852 void PF_te_superspike (void)
1854 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1855 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1857 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1858 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1859 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1862 void PF_te_explosion (void)
1864 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1865 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1868 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1869 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1872 void PF_te_tarexplosion (void)
1874 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1875 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1877 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1878 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1879 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1882 void PF_te_wizspike (void)
1884 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1885 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1887 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1888 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1889 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1892 void PF_te_knightspike (void)
1894 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1895 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1902 void PF_te_lavasplash (void)
1904 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1905 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1912 void PF_te_teleport (void)
1914 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1915 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1917 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1918 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1919 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1922 void PF_te_explosion2 (void)
1924 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1925 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1931 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
1932 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
1935 void PF_te_lightning1 (void)
1937 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1938 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
1940 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1942 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1943 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1944 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1948 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1951 void PF_te_lightning2 (void)
1953 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1954 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
1956 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1964 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1967 void PF_te_lightning3 (void)
1969 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1970 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
1972 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1974 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1975 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1976 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1978 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1979 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1980 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1983 void PF_te_beam (void)
1985 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1986 MSG_WriteByte(&sv.datagram, TE_BEAM);
1988 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1990 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1991 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1992 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1994 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1995 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1996 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1999 void PF_te_plasmaburn (void)
2001 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2002 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2004 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2005 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2008 void PF_te_flamejet (void)
2010 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2011 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2014 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2015 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2017 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2018 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2019 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2021 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2024 void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2027 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2029 bestdist = 1000000000;
2031 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2033 // clip original point to each triangle of the surface and find the
2034 // triangle that is closest
2035 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2036 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2037 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2038 TriangleNormal(v[0], v[1], v[2], facenormal);
2039 VectorNormalize(facenormal);
2040 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2041 VectorMA(p, offsetdist, facenormal, temp);
2042 for (j = 0, k = 2;j < 3;k = j, j++)
2044 VectorSubtract(v[k], v[j], edgenormal);
2045 CrossProduct(edgenormal, facenormal, sidenormal);
2046 VectorNormalize(sidenormal);
2047 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2049 VectorMA(temp, offsetdist, sidenormal, temp);
2051 dist = VectorDistance2(temp, p);
2052 if (bestdist > dist)
2055 VectorCopy(temp, out);
2060 static model_t *getmodel(prvm_edict_t *ed)
2063 if (!ed || ed->priv.server->free)
2065 modelindex = (int)ed->fields.server->modelindex;
2066 if (modelindex < 1 || modelindex >= MAX_MODELS)
2068 return sv.models[modelindex];
2071 static msurface_t *getsurface(model_t *model, int surfacenum)
2073 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2075 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2079 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2080 void PF_getsurfacenumpoints(void)
2083 msurface_t *surface;
2084 // return 0 if no such surface
2085 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2087 PRVM_G_FLOAT(OFS_RETURN) = 0;
2091 // note: this (incorrectly) assumes it is a simple polygon
2092 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2094 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2095 void PF_getsurfacepoint(void)
2099 msurface_t *surface;
2101 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2102 ed = PRVM_G_EDICT(OFS_PARM0);
2103 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2105 // note: this (incorrectly) assumes it is a simple polygon
2106 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2107 if (pointnum < 0 || pointnum >= surface->num_vertices)
2109 // FIXME: implement rotation/scaling
2110 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2112 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2113 void PF_getsurfacenormal(void)
2116 msurface_t *surface;
2118 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2119 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2121 // FIXME: implement rotation/scaling
2122 // note: this (incorrectly) assumes it is a simple polygon
2123 // note: this only returns the first triangle, so it doesn't work very
2124 // well for curved surfaces or arbitrary meshes
2125 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);
2126 VectorNormalize(normal);
2127 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2129 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2130 void PF_getsurfacetexture(void)
2133 msurface_t *surface;
2134 PRVM_G_INT(OFS_RETURN) = 0;
2135 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2137 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
2139 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2140 void PF_getsurfacenearpoint(void)
2142 int surfacenum, best;
2144 vec_t dist, bestdist;
2147 msurface_t *surface;
2149 PRVM_G_FLOAT(OFS_RETURN) = -1;
2150 ed = PRVM_G_EDICT(OFS_PARM0);
2151 point = PRVM_G_VECTOR(OFS_PARM1);
2153 if (!ed || ed->priv.server->free)
2155 model = getmodel(ed);
2156 if (!model || !model->num_surfaces)
2159 // FIXME: implement rotation/scaling
2160 VectorSubtract(point, ed->fields.server->origin, p);
2162 bestdist = 1000000000;
2163 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2165 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2166 // first see if the nearest point on the surface's box is closer than the previous match
2167 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2168 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2169 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2170 dist = VectorLength2(clipped);
2171 if (dist < bestdist)
2173 // it is, check the nearest point on the actual geometry
2174 clippointtosurface(model, surface, p, clipped);
2175 VectorSubtract(clipped, p, clipped);
2176 dist += VectorLength2(clipped);
2177 if (dist < bestdist)
2179 // that's closer too, store it as the best match
2185 PRVM_G_FLOAT(OFS_RETURN) = best;
2187 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2188 void PF_getsurfaceclippedpoint(void)
2192 msurface_t *surface;
2194 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2195 ed = PRVM_G_EDICT(OFS_PARM0);
2196 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2198 // FIXME: implement rotation/scaling
2199 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2200 clippointtosurface(model, surface, p, out);
2201 // FIXME: implement rotation/scaling
2202 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2205 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2206 //this function originally written by KrimZon, made shorter by LordHavoc
2207 void PF_clientcommand (void)
2209 client_t *temp_client;
2212 //find client for this entity
2213 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2214 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2216 Con_Print("PF_clientcommand: entity is not a client\n");
2220 temp_client = host_client;
2221 host_client = svs.clients + i;
2222 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2223 host_client = temp_client;
2226 //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)
2227 void PF_setattachment (void)
2229 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2230 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2231 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2236 if (e == prog->edicts)
2237 PF_WARNING("setattachment: can not modify world entity\n");
2238 if (e->priv.server->free)
2239 PF_WARNING("setattachment: can not modify free entity\n");
2241 if (tagentity == NULL)
2242 tagentity = prog->edicts;
2244 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2246 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2248 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2251 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2253 modelindex = (int)tagentity->fields.server->modelindex;
2254 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2256 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2258 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);
2261 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));
2265 /////////////////////////////////////////
2266 // DP_MD3_TAGINFO extension coded by VorteX
2268 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2273 i = (int)e->fields.server->modelindex;
2274 if (i < 1 || i >= MAX_MODELS)
2276 model = sv.models[i];
2278 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2281 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2283 float scale = PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float;
2287 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);
2289 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);
2292 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2298 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2299 && (model = sv.models[(int)ent->fields.server->modelindex])
2300 && model->animscenes)
2302 // if model has wrong frame, engine automatically switches to model first frame
2303 frame = (int)ent->fields.server->frame;
2304 if (frame < 0 || frame >= model->numframes)
2306 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2308 *out = identitymatrix;
2312 // Warnings/errors code:
2313 // 0 - normal (everything all-right)
2316 // 3 - null or non-precached model
2317 // 4 - no tags with requested index
2318 // 5 - runaway loop at attachment chain
2319 extern cvar_t cl_bob;
2320 extern cvar_t cl_bobcycle;
2321 extern cvar_t cl_bobup;
2322 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2326 int modelindex, attachloop;
2327 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2330 *out = identitymatrix; // warnings and errors return identical matrix
2332 if (ent == prog->edicts)
2334 if (ent->priv.server->free)
2337 modelindex = (int)ent->fields.server->modelindex;
2338 if (modelindex <= 0 || modelindex > MAX_MODELS)
2341 model = sv.models[modelindex];
2343 tagmatrix = identitymatrix;
2344 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2348 if (attachloop >= 256) // prevent runaway looping
2350 // apply transformation by child's tagindex on parent entity and then
2351 // by parent entity itself
2352 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2353 if (ret && attachloop == 0)
2355 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2356 SV_GetEntityMatrix(ent, &entitymatrix, false);
2357 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2358 // next iteration we process the parent entity
2359 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2361 tagindex = (int)PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
2362 ent = PRVM_EDICT_NUM(val->edict);
2369 // RENDER_VIEWMODEL magic
2370 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2372 Matrix4x4_Copy(&tagmatrix, out);
2373 ent = PRVM_EDICT_NUM(val->edict);
2375 SV_GetEntityMatrix(ent, &entitymatrix, true);
2376 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2379 // Cl_bob, ported from rendering code
2380 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2383 // LordHavoc: this code is *weird*, but not replacable (I think it
2384 // should be done in QC on the server, but oh well, quake is quake)
2385 // LordHavoc: figured out bobup: the time at which the sin is at 180
2386 // degrees (which allows lengthening or squishing the peak or valley)
2387 cycle = sv.time/cl_bobcycle.value;
2388 cycle -= (int)cycle;
2389 if (cycle < cl_bobup.value)
2390 cycle = sin(M_PI * cycle / cl_bobup.value);
2392 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2393 // bob is proportional to velocity in the xy plane
2394 // (don't count Z, or jumping messes it up)
2395 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;
2396 bob = bob*0.3 + bob*0.7*cycle;
2397 out->m[2][3] += bound(-7, bob, 4);
2404 //float(entity ent, string tagname) gettagindex;
2406 void PF_gettagindex (void)
2408 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2409 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2410 int modelindex, tag_index;
2412 if (ent == prog->edicts)
2413 PF_WARNING("gettagindex: can't affect world entity\n");
2414 if (ent->priv.server->free)
2415 PF_WARNING("gettagindex: can't affect free entity\n");
2417 modelindex = (int)ent->fields.server->modelindex;
2419 if (modelindex <= 0 || modelindex > MAX_MODELS)
2420 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2423 tag_index = SV_GetTagIndex(ent, tag_name);
2425 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2427 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2430 //vector(entity ent, float tagindex) gettaginfo;
2431 void PF_gettaginfo (void)
2433 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2434 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2435 matrix4x4_t tag_matrix;
2438 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2439 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2444 PF_WARNING("gettagindex: can't affect world entity\n");
2447 PF_WARNING("gettagindex: can't affect free entity\n");
2450 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2453 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2456 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2461 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2462 void PF_dropclient (void)
2465 client_t *oldhostclient;
2466 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2467 if (clientnum < 0 || clientnum >= svs.maxclients)
2468 PF_WARNING("dropclient: not a client\n");
2469 if (!svs.clients[clientnum].active)
2470 PF_WARNING("dropclient: that client slot is not connected\n");
2471 oldhostclient = host_client;
2472 host_client = svs.clients + clientnum;
2473 SV_DropClient(false);
2474 host_client = oldhostclient;
2477 //entity() spawnclient (DP_SV_BOTCLIENT)
2478 void PF_spawnclient (void)
2482 prog->xfunction->builtinsprofile += 2;
2484 for (i = 0;i < svs.maxclients;i++)
2486 if (!svs.clients[i].active)
2488 prog->xfunction->builtinsprofile += 100;
2489 SV_ConnectClient (i, NULL);
2490 // this has to be set or else ClientDisconnect won't be called
2491 // we assume the qc will call ClientConnect...
2492 svs.clients[i].clientconnectcalled = true;
2493 ed = PRVM_EDICT_NUM(i + 1);
2497 VM_RETURN_EDICT(ed);
2500 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2501 void PF_clienttype (void)
2504 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2505 if (clientnum < 0 || clientnum >= svs.maxclients)
2506 PRVM_G_FLOAT(OFS_RETURN) = 3;
2507 else if (!svs.clients[clientnum].active)
2508 PRVM_G_FLOAT(OFS_RETURN) = 0;
2509 else if (svs.clients[clientnum].netconnection)
2510 PRVM_G_FLOAT(OFS_RETURN) = 1;
2512 PRVM_G_FLOAT(OFS_RETURN) = 2;
2515 void PF_edict_num (void)
2517 VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0)));
2520 prvm_builtin_t vm_sv_builtins[] = {
2522 PF_makevectors, // #1 void(vector ang) makevectors
2523 PF_setorigin, // #2 void(entity e, vector o) setorigin
2524 PF_setmodel, // #3 void(entity e, string m) setmodel
2525 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2526 NULL, // #5 void(entity e, vector min, vector max) setabssize
2527 VM_break, // #6 void() break
2528 VM_random, // #7 float() random
2529 PF_sound, // #8 void(entity e, float chan, string samp) sound
2530 VM_normalize, // #9 vector(vector v) normalize
2531 VM_error, // #10 void(string e) error
2532 VM_objerror, // #11 void(string e) objerror
2533 VM_vlen, // #12 float(vector v) vlen
2534 VM_vectoyaw, // #13 float(vector v) vectoyaw
2535 VM_spawn, // #14 entity() spawn
2536 VM_remove, // #15 void(entity e) remove
2537 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2538 PF_checkclient, // #17 entity() clientlist
2539 VM_find, // #18 entity(entity start, .string fld, string match) find
2540 PF_precache_sound, // #19 void(string s) precache_sound
2541 PF_precache_model, // #20 void(string s) precache_model
2542 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2543 PF_findradius, // #22 entity(vector org, float rad) findradius
2544 VM_bprint, // #23 void(string s) bprint
2545 PF_sprint, // #24 void(entity client, string s) sprint
2546 VM_dprint, // #25 void(string s) dprint
2547 VM_ftos, // #26 void(string s) ftos
2548 VM_vtos, // #27 void(string s) vtos
2549 VM_coredump, // #28 void() coredump
2550 VM_traceon, // #29 void() traceon
2551 VM_traceoff, // #30 void() traceoff
2552 VM_eprint, // #31 void(entity e) eprint
2553 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2555 PF_droptofloor, // #34 float() droptofloor
2556 PF_lightstyle, // #35 void(float style, string value) lightstyle
2557 VM_rint, // #36 float(float v) rint
2558 VM_floor, // #37 float(float v) floor
2559 VM_ceil, // #38 float(float v) ceil
2561 PF_checkbottom, // #40 float(entity e) checkbottom
2562 PF_pointcontents, // #41 float(vector v) pointcontents
2564 VM_fabs, // #43 float(float f) fabs
2565 PF_aim, // #44 vector(entity e, float speed) aim
2566 VM_cvar, // #45 float(string s) cvar
2567 VM_localcmd, // #46 void(string s) localcmd
2568 VM_nextent, // #47 entity(entity e) nextent
2569 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2570 PF_changeyaw, // #49 void() ChangeYaw
2572 VM_vectoangles, // #51 vector(vector v) vectoangles
2573 PF_WriteByte, // #52 void(float to, float f) WriteByte
2574 PF_WriteChar, // #53 void(float to, float f) WriteChar
2575 PF_WriteShort, // #54 void(float to, float f) WriteShort
2576 PF_WriteLong, // #55 void(float to, float f) WriteLong
2577 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2578 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2579 PF_WriteString, // #58 void(float to, string s) WriteString
2580 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2581 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2582 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2583 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2584 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2585 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2586 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2588 SV_MoveToGoal, // #67 void(float step) movetogoal
2589 PF_precache_file, // #68 string(string s) precache_file
2590 PF_makestatic, // #69 void(entity e) makestatic
2591 VM_changelevel, // #70 void(string s) changelevel
2593 VM_cvar_set, // #72 void(string var, string val) cvar_set
2594 PF_centerprint, // #73 void(entity client, strings) centerprint
2595 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2596 PF_precache_model, // #75 string(string s) precache_model2
2597 PF_precache_sound, // #76 string(string s) precache_sound2
2598 PF_precache_file, // #77 string(string s) precache_file2
2599 PF_setspawnparms, // #78 void(entity e) setspawnparms
2602 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2611 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2612 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2613 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2614 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2615 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2616 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2617 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2618 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2619 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2620 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2631 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2632 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2633 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2634 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2635 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2636 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2637 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2638 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2639 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2640 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2641 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2642 // FTEQW range #200-#299
2661 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2671 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2672 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2673 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2674 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2675 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2676 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2677 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2678 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2679 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2680 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2681 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2682 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2683 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2684 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2685 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2686 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2687 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2688 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2689 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2690 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2691 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2692 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2693 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2694 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2695 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2696 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2697 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2698 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2699 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2700 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2701 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2702 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2703 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2704 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2705 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2706 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2707 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2708 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2709 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2710 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2711 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2712 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2713 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2714 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2715 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2716 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2717 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2718 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2719 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2720 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2721 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2722 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2723 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2724 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2725 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2726 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2727 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2728 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2729 PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2731 PF_edict_num, // #459 entity(float num) (??)
2732 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2733 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2734 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2735 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2736 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2737 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2738 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2739 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2740 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2741 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2742 PF_SV_AddStat, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2752 e10, e10 // #480-499 (LordHavoc)
2755 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2757 void VM_SV_Cmd_Init(void)
2762 void VM_SV_Cmd_Reset(void)