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 "
39 "DP_GFX_QUAKE3MODELTAGS "
43 "DP_HALFLIFE_MAP_CVAR "
49 "DP_MOVETYPEBOUNCEMISSILE "
56 "DP_QC_FINDCHAINFLAGS "
57 "DP_QC_FINDCHAINFLOAT "
60 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
65 "DP_QC_MULTIPLETEMPSTRINGS "
67 "DP_QC_SINCOSSQRTPOW "
68 "DP_QC_STRINGBUFFERS "
71 "DP_QC_TRACE_MOVETYPE_HITMODEL "
72 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
73 "DP_QC_VECTORVECTORS "
79 "DP_SND_DIRECTIONLESSATTNNONE "
88 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
89 "DP_SV_DRAWONLYTOCLIENT "
92 "DP_SV_NODRAWTOCLIENT "
94 "DP_SV_PLAYERPHYSICS "
95 "DP_SV_PRECACHEANYTIME "
97 "DP_SV_ROTATINGBMODEL "
100 "DP_SV_WRITEUNTERMINATEDSTRING "
104 "DP_TE_EXPLOSIONRGB "
106 "DP_TE_PARTICLECUBE "
107 "DP_TE_PARTICLERAIN "
108 "DP_TE_PARTICLESNOW "
110 "DP_TE_QUADEFFECTS1 "
113 "DP_TE_STANDARDEFFECTBUILTINS "
114 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
117 //"EXT_CSQC " // not ready yet
119 "KRIMZON_SV_PARSECLIENTCOMMAND "
123 "PRYDON_CLIENTCURSOR "
124 "TENEBRAE_GFX_DLIGHTS "
126 "NEXUIZ_PLAYERMODEL "
133 Writes new values for v_forward, v_up, and v_right based on angles
137 void PF_makevectors (void)
139 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
146 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.
148 setorigin (entity, origin)
151 void PF_setorigin (void)
156 e = PRVM_G_EDICT(OFS_PARM0);
157 if (e == prog->edicts)
158 PF_WARNING("setorigin: can not modify world entity\n");
159 if (e->priv.server->free)
160 PF_WARNING("setorigin: can not modify free entity\n");
161 org = PRVM_G_VECTOR(OFS_PARM1);
162 VectorCopy (org, e->fields.server->origin);
163 SV_LinkEdict (e, false);
167 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
171 for (i=0 ; i<3 ; i++)
173 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
175 // set derived values
176 VectorCopy (min, e->fields.server->mins);
177 VectorCopy (max, e->fields.server->maxs);
178 VectorSubtract (max, min, e->fields.server->size);
180 SV_LinkEdict (e, false);
187 the size box is rotated by the current angle
188 LordHavoc: no it isn't...
190 setsize (entity, minvector, maxvector)
193 void PF_setsize (void)
198 e = PRVM_G_EDICT(OFS_PARM0);
199 if (e == prog->edicts)
200 PF_WARNING("setsize: can not modify world entity\n");
201 if (e->priv.server->free)
202 PF_WARNING("setsize: can not modify free entity\n");
203 min = PRVM_G_VECTOR(OFS_PARM1);
204 max = PRVM_G_VECTOR(OFS_PARM2);
205 SetMinMaxSize (e, min, max, false);
213 setmodel(entity, model)
216 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
217 void PF_setmodel (void)
223 e = PRVM_G_EDICT(OFS_PARM0);
224 if (e == prog->edicts)
225 PF_WARNING("setmodel: can not modify world entity\n");
226 if (e->priv.server->free)
227 PF_WARNING("setmodel: can not modify free entity\n");
228 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
229 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
230 e->fields.server->modelindex = i;
236 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
237 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
239 SetMinMaxSize (e, quakemins, quakemaxs, true);
242 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
249 single print to a specific client
251 sprint(clientent, value)
254 void PF_sprint (void)
258 char string[VM_STRINGTEMP_LENGTH];
260 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
262 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
264 Con_Print("tried to sprint to a non-client\n");
268 client = svs.clients + entnum-1;
269 if (!client->netconnection)
272 VM_VarString(1, string, sizeof(string));
273 MSG_WriteChar(&client->netconnection->message,svc_print);
274 MSG_WriteString(&client->netconnection->message, string);
282 single print to a specific client
284 centerprint(clientent, value)
287 void PF_centerprint (void)
291 char string[VM_STRINGTEMP_LENGTH];
293 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
295 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
297 Con_Print("tried to sprint to a non-client\n");
301 client = svs.clients + entnum-1;
302 if (!client->netconnection)
305 VM_VarString(1, string, sizeof(string));
306 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
307 MSG_WriteString(&client->netconnection->message, string);
314 particle(origin, color, count)
317 void PF_particle (void)
323 org = PRVM_G_VECTOR(OFS_PARM0);
324 dir = PRVM_G_VECTOR(OFS_PARM1);
325 color = PRVM_G_FLOAT(OFS_PARM2);
326 count = PRVM_G_FLOAT(OFS_PARM3);
327 SV_StartParticle (org, dir, (int)color, (int)count);
337 void PF_ambientsound (void)
341 float vol, attenuation;
344 pos = PRVM_G_VECTOR (OFS_PARM0);
345 samp = PRVM_G_STRING(OFS_PARM1);
346 vol = PRVM_G_FLOAT(OFS_PARM2);
347 attenuation = PRVM_G_FLOAT(OFS_PARM3);
349 // check to see if samp was properly precached
350 soundnum = SV_SoundIndex(samp, 1);
358 // add an svc_spawnambient command to the level signon packet
361 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
363 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
365 MSG_WriteVector(&sv.signon, pos, sv.protocol);
368 MSG_WriteShort (&sv.signon, soundnum);
370 MSG_WriteByte (&sv.signon, soundnum);
372 MSG_WriteByte (&sv.signon, (int)(vol*255));
373 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
381 Each entity can have eight independant sound sources, like voice,
384 Channel 0 is an auto-allocate channel, the others override anything
385 already running on that entity/channel pair.
387 An attenuation of 0 will play full volume everywhere in the level.
388 Larger attenuations will drop off.
396 prvm_edict_t *entity;
400 entity = PRVM_G_EDICT(OFS_PARM0);
401 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
402 sample = PRVM_G_STRING(OFS_PARM2);
403 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
404 attenuation = PRVM_G_FLOAT(OFS_PARM4);
406 if (volume < 0 || volume > 255)
407 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
409 if (attenuation < 0 || attenuation > 4)
410 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
412 if (channel < 0 || channel > 7)
413 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
415 SV_StartSound (entity, channel, sample, volume, attenuation);
422 Used for use tracing and shot targeting
423 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
424 if the tryents flag is set.
426 traceline (vector1, vector2, tryents)
429 void PF_traceline (void)
437 prog->xfunction->builtinsprofile += 30;
439 v1 = PRVM_G_VECTOR(OFS_PARM0);
440 v2 = PRVM_G_VECTOR(OFS_PARM1);
441 move = (int)PRVM_G_FLOAT(OFS_PARM2);
442 ent = PRVM_G_EDICT(OFS_PARM3);
444 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]))
445 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));
447 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
449 prog->globals.server->trace_allsolid = trace.allsolid;
450 prog->globals.server->trace_startsolid = trace.startsolid;
451 prog->globals.server->trace_fraction = trace.fraction;
452 prog->globals.server->trace_inwater = trace.inwater;
453 prog->globals.server->trace_inopen = trace.inopen;
454 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
455 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
456 prog->globals.server->trace_plane_dist = trace.plane.dist;
458 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
460 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
461 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
462 val->_float = trace.startsupercontents;
463 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
464 val->_float = trace.hitsupercontents;
465 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
466 val->_float = trace.hitq3surfaceflags;
467 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
469 if (trace.hittexture)
471 char *s = VM_GetTempString();
472 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
473 val->string = PRVM_SetEngineString(s);
485 Used for use tracing and shot targeting
486 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
487 if the tryents flag is set.
489 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
492 // LordHavoc: added this for my own use, VERY useful, similar to traceline
493 void PF_tracebox (void)
495 float *v1, *v2, *m1, *m2;
501 prog->xfunction->builtinsprofile += 30;
503 v1 = PRVM_G_VECTOR(OFS_PARM0);
504 m1 = PRVM_G_VECTOR(OFS_PARM1);
505 m2 = PRVM_G_VECTOR(OFS_PARM2);
506 v2 = PRVM_G_VECTOR(OFS_PARM3);
507 move = (int)PRVM_G_FLOAT(OFS_PARM4);
508 ent = PRVM_G_EDICT(OFS_PARM5);
510 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]))
511 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));
513 trace = SV_Move (v1, m1, m2, v2, move, ent);
515 prog->globals.server->trace_allsolid = trace.allsolid;
516 prog->globals.server->trace_startsolid = trace.startsolid;
517 prog->globals.server->trace_fraction = trace.fraction;
518 prog->globals.server->trace_inwater = trace.inwater;
519 prog->globals.server->trace_inopen = trace.inopen;
520 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
521 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
522 prog->globals.server->trace_plane_dist = trace.plane.dist;
524 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
526 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
527 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
528 val->_float = trace.startsupercontents;
529 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
530 val->_float = trace.hitsupercontents;
531 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
532 val->_float = trace.hitq3surfaceflags;
533 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
535 if (trace.hittexture)
537 char *s = VM_GetTempString();
538 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
539 val->string = PRVM_SetEngineString(s);
546 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
547 void PF_tracetoss (void)
551 prvm_edict_t *ignore;
554 prog->xfunction->builtinsprofile += 600;
556 ent = PRVM_G_EDICT(OFS_PARM0);
557 if (ent == prog->edicts)
558 PF_WARNING("tracetoss: can not use world entity\n");
559 ignore = PRVM_G_EDICT(OFS_PARM1);
561 trace = SV_Trace_Toss (ent, ignore);
563 prog->globals.server->trace_allsolid = trace.allsolid;
564 prog->globals.server->trace_startsolid = trace.startsolid;
565 prog->globals.server->trace_fraction = trace.fraction;
566 prog->globals.server->trace_inwater = trace.inwater;
567 prog->globals.server->trace_inopen = trace.inopen;
568 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
569 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
570 prog->globals.server->trace_plane_dist = trace.plane.dist;
572 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
574 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
575 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
576 val->_float = trace.startsupercontents;
577 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
578 val->_float = trace.hitsupercontents;
579 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
580 val->_float = trace.hitq3surfaceflags;
581 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
583 if (trace.hittexture)
585 char *s = VM_GetTempString();
586 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
587 val->string = PRVM_SetEngineString(s);
599 Returns true if the given entity can move to the given position from it's
600 current position by walking or rolling.
602 scalar checkpos (entity, vector)
605 void PF_checkpos (void)
609 //============================================================================
612 unsigned char checkpvs[MAX_MAP_LEAFS/8];
614 int PF_newcheckclient (int check)
620 // cycle to the next one
622 check = bound(1, check, svs.maxclients);
623 if (check == svs.maxclients)
631 prog->xfunction->builtinsprofile++;
633 if (i == svs.maxclients+1)
635 // look up the client's edict
636 ent = PRVM_EDICT_NUM(i);
637 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
638 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
640 // found a valid client (possibly the same one again)
644 // get the PVS for the entity
645 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
647 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
648 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
657 Returns a client (or object that has a client enemy) that would be a
660 If there is more than one valid option, they are cycled each frame
662 If (self.origin + self.viewofs) is not in the PVS of the current target,
663 it is not returned at all.
668 int c_invis, c_notvis;
669 void PF_checkclient (void)
671 prvm_edict_t *ent, *self;
674 // find a new check if on a new frame
675 if (sv.time - sv.lastchecktime >= 0.1)
677 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
678 sv.lastchecktime = sv.time;
681 // return check if it might be visible
682 ent = PRVM_EDICT_NUM(sv.lastcheck);
683 if (ent->priv.server->free || ent->fields.server->health <= 0)
685 VM_RETURN_EDICT(prog->edicts);
689 // if current entity can't possibly see the check entity, return 0
690 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
691 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
692 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
695 VM_RETURN_EDICT(prog->edicts);
699 // might be able to see it
701 VM_RETURN_EDICT(ent);
704 //============================================================================
711 Sends text over to the client's execution buffer
713 stuffcmd (clientent, value, ...)
716 void PF_stuffcmd (void)
720 char string[VM_STRINGTEMP_LENGTH];
722 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
723 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
725 Con_Print("Can't stuffcmd to a non-client\n");
729 VM_VarString(1, string, sizeof(string));
732 host_client = svs.clients + entnum-1;
733 Host_ClientCommands ("%s", string);
741 Returns a chain of entities that have origins within a spherical area
743 findradius (origin, radius)
746 void PF_findradius (void)
748 prvm_edict_t *ent, *chain;
749 vec_t radius, radius2;
750 vec3_t org, eorg, mins, maxs;
753 prvm_edict_t *touchedicts[MAX_EDICTS];
755 chain = (prvm_edict_t *)prog->edicts;
757 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
758 radius = PRVM_G_FLOAT(OFS_PARM1);
759 radius2 = radius * radius;
761 mins[0] = org[0] - (radius + 1);
762 mins[1] = org[1] - (radius + 1);
763 mins[2] = org[2] - (radius + 1);
764 maxs[0] = org[0] + (radius + 1);
765 maxs[1] = org[1] + (radius + 1);
766 maxs[2] = org[2] + (radius + 1);
767 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
768 if (numtouchedicts > MAX_EDICTS)
770 // this never happens
771 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
772 numtouchedicts = MAX_EDICTS;
774 for (i = 0;i < numtouchedicts;i++)
776 ent = touchedicts[i];
777 prog->xfunction->builtinsprofile++;
778 // Quake did not return non-solid entities but darkplaces does
779 // (note: this is the reason you can't blow up fallen zombies)
780 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
782 // LordHavoc: compare against bounding box rather than center so it
783 // doesn't miss large objects, and use DotProduct instead of Length
784 // for a major speedup
785 VectorSubtract(org, ent->fields.server->origin, eorg);
786 if (sv_gameplayfix_findradiusdistancetobox.integer)
788 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
789 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
790 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
793 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
794 if (DotProduct(eorg, eorg) < radius2)
796 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
801 VM_RETURN_EDICT(chain);
804 void PF_precache_file (void)
805 { // precache_file is only used to copy files with qcc, it does nothing
806 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
810 void PF_precache_sound (void)
812 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
813 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
816 void PF_precache_model (void)
818 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
819 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
826 float(float yaw, float dist) walkmove
829 void PF_walkmove (void)
837 // assume failure if it returns early
838 PRVM_G_FLOAT(OFS_RETURN) = 0;
840 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
841 if (ent == prog->edicts)
842 PF_WARNING("walkmove: can not modify world entity\n");
843 if (ent->priv.server->free)
844 PF_WARNING("walkmove: can not modify free entity\n");
845 yaw = PRVM_G_FLOAT(OFS_PARM0);
846 dist = PRVM_G_FLOAT(OFS_PARM1);
848 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
851 yaw = yaw*M_PI*2 / 360;
853 move[0] = cos(yaw)*dist;
854 move[1] = sin(yaw)*dist;
857 // save program state, because SV_movestep may call other progs
858 oldf = prog->xfunction;
859 oldself = prog->globals.server->self;
861 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
864 // restore program state
865 prog->xfunction = oldf;
866 prog->globals.server->self = oldself;
876 void PF_droptofloor (void)
882 // assume failure if it returns early
883 PRVM_G_FLOAT(OFS_RETURN) = 0;
885 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
886 if (ent == prog->edicts)
887 PF_WARNING("droptofloor: can not modify world entity\n");
888 if (ent->priv.server->free)
889 PF_WARNING("droptofloor: can not modify free entity\n");
891 VectorCopy (ent->fields.server->origin, end);
894 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
896 if (trace.fraction != 1)
898 VectorCopy (trace.endpos, ent->fields.server->origin);
899 SV_LinkEdict (ent, false);
900 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
901 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
902 PRVM_G_FLOAT(OFS_RETURN) = 1;
903 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
904 ent->priv.server->suspendedinairflag = true;
912 void(float style, string value) lightstyle
915 void PF_lightstyle (void)
922 style = (int)PRVM_G_FLOAT(OFS_PARM0);
923 val = PRVM_G_STRING(OFS_PARM1);
925 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
926 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
929 // change the string in sv
930 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
932 // send message to all clients on this server
933 if (sv.state != ss_active)
936 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
938 if (client->active && client->netconnection)
940 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
941 MSG_WriteChar (&client->netconnection->message,style);
942 MSG_WriteString (&client->netconnection->message, val);
952 void PF_checkbottom (void)
954 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
962 void PF_pointcontents (void)
964 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
971 Pick a vector for the player to shoot along
972 vector aim(entity, missilespeed)
977 prvm_edict_t *ent, *check, *bestent;
978 vec3_t start, dir, end, bestdir;
981 float dist, bestdist;
984 // assume failure if it returns early
985 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
986 // if sv_aim is so high it can't possibly accept anything, skip out early
987 if (sv_aim.value >= 1)
990 ent = PRVM_G_EDICT(OFS_PARM0);
991 if (ent == prog->edicts)
992 PF_WARNING("aim: can not use world entity\n");
993 if (ent->priv.server->free)
994 PF_WARNING("aim: can not use free entity\n");
995 speed = PRVM_G_FLOAT(OFS_PARM1);
997 VectorCopy (ent->fields.server->origin, start);
1000 // try sending a trace straight
1001 VectorCopy (prog->globals.server->v_forward, dir);
1002 VectorMA (start, 2048, dir, end);
1003 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1004 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1005 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1007 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1012 // try all possible entities
1013 VectorCopy (dir, bestdir);
1014 bestdist = sv_aim.value;
1017 check = PRVM_NEXT_EDICT(prog->edicts);
1018 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1020 prog->xfunction->builtinsprofile++;
1021 if (check->fields.server->takedamage != DAMAGE_AIM)
1025 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1026 continue; // don't aim at teammate
1027 for (j=0 ; j<3 ; j++)
1028 end[j] = check->fields.server->origin[j]
1029 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1030 VectorSubtract (end, start, dir);
1031 VectorNormalize (dir);
1032 dist = DotProduct (dir, prog->globals.server->v_forward);
1033 if (dist < bestdist)
1034 continue; // to far to turn
1035 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1036 if (tr.ent == check)
1037 { // can shoot at this one
1045 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1046 dist = DotProduct (dir, prog->globals.server->v_forward);
1047 VectorScale (prog->globals.server->v_forward, dist, end);
1049 VectorNormalize (end);
1050 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1054 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1062 This was a major timewaster in progs, so it was converted to C
1065 void PF_changeyaw (void)
1068 float ideal, current, move, speed;
1070 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1071 if (ent == prog->edicts)
1072 PF_WARNING("changeyaw: can not modify world entity\n");
1073 if (ent->priv.server->free)
1074 PF_WARNING("changeyaw: can not modify free entity\n");
1075 current = ANGLEMOD(ent->fields.server->angles[1]);
1076 ideal = ent->fields.server->ideal_yaw;
1077 speed = ent->fields.server->yaw_speed;
1079 if (current == ideal)
1081 move = ideal - current;
1082 if (ideal > current)
1103 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1111 void PF_changepitch (void)
1114 float ideal, current, move, speed;
1117 ent = PRVM_G_EDICT(OFS_PARM0);
1118 if (ent == prog->edicts)
1119 PF_WARNING("changepitch: can not modify world entity\n");
1120 if (ent->priv.server->free)
1121 PF_WARNING("changepitch: can not modify free entity\n");
1122 current = ANGLEMOD( ent->fields.server->angles[0] );
1123 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1124 ideal = val->_float;
1127 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1130 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1131 speed = val->_float;
1134 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1138 if (current == ideal)
1140 move = ideal - current;
1141 if (ideal > current)
1162 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1166 ===============================================================================
1170 ===============================================================================
1173 #define MSG_BROADCAST 0 // unreliable to all
1174 #define MSG_ONE 1 // reliable to one (msg_entity)
1175 #define MSG_ALL 2 // reliable to all
1176 #define MSG_INIT 3 // write to the init string
1177 #define MSG_ENTITY 5
1179 sizebuf_t *WriteDest (void)
1184 extern sizebuf_t *sv2csqcbuf;
1186 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1190 return &sv.datagram;
1193 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1194 entnum = PRVM_NUM_FOR_EDICT(ent);
1195 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1197 Con_Printf ("WriteDest: tried to write to non-client\n");
1198 return &sv.reliable_datagram;
1201 return &svs.clients[entnum-1].netconnection->message;
1204 Con_Printf ("WriteDest: bad destination\n");
1206 return &sv.reliable_datagram;
1218 void PF_WriteByte (void)
1220 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1223 void PF_WriteChar (void)
1225 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1228 void PF_WriteShort (void)
1230 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1233 void PF_WriteLong (void)
1235 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1238 void PF_WriteAngle (void)
1240 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1243 void PF_WriteCoord (void)
1245 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1248 void PF_WriteString (void)
1250 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1253 void PF_WriteUnterminatedString (void)
1255 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1259 void PF_WriteEntity (void)
1261 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1264 //////////////////////////////////////////////////////////
1266 void PF_makestatic (void)
1271 ent = PRVM_G_EDICT(OFS_PARM0);
1272 if (ent == prog->edicts)
1273 PF_WARNING("makestatic: can not modify world entity\n");
1274 if (ent->priv.server->free)
1275 PF_WARNING("makestatic: can not modify free entity\n");
1278 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1283 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1284 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1285 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1289 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1290 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1291 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1294 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1295 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1296 for (i=0 ; i<3 ; i++)
1298 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1299 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1302 // throw the entity away now
1306 //=============================================================================
1313 void PF_setspawnparms (void)
1319 ent = PRVM_G_EDICT(OFS_PARM0);
1320 i = PRVM_NUM_FOR_EDICT(ent);
1321 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1323 Con_Print("tried to setspawnparms on a non-client\n");
1327 // copy spawn parms out of the client_t
1328 client = svs.clients + i-1;
1329 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1330 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1337 Returns a color vector indicating the lighting at the requested point.
1339 (Internal Operation note: actually measures the light beneath the point, just like
1340 the model lighting on the client)
1345 void PF_getlight (void)
1347 vec3_t ambientcolor, diffusecolor, diffusenormal;
1349 p = PRVM_G_VECTOR(OFS_PARM0);
1350 VectorClear(ambientcolor);
1351 VectorClear(diffusecolor);
1352 VectorClear(diffusenormal);
1353 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1354 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1355 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1358 void PF_registercvar (void)
1360 const char *name, *value;
1361 name = PRVM_G_STRING(OFS_PARM0);
1362 value = PRVM_G_STRING(OFS_PARM1);
1363 PRVM_G_FLOAT(OFS_RETURN) = 0;
1365 // first check to see if it has already been defined
1366 if (Cvar_FindVar (name))
1369 // check for overlap with a command
1370 if (Cmd_Exists (name))
1372 Con_Printf("PF_registercvar: %s is a command\n", name);
1376 Cvar_Get(name, value, 0);
1378 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1383 unsigned char type; // 1/2/8 or other value if isn't used
1387 static autosentstat_t *vm_autosentstats = NULL; //[515]: it starts from 0, not 32
1388 static int vm_autosentstats_last;
1390 void VM_AutoSentStats_Clear (void)
1392 if(vm_autosentstats)
1394 Z_Free(vm_autosentstats);
1395 vm_autosentstats = NULL;
1396 vm_autosentstats_last = -1;
1400 //[515]: add check if even bigger ? "try to use two stats, cause it's too big" ?
1401 #define VM_SENDSTAT(a,b,c)\
1404 if((c)==(unsigned char)(c))\
1406 MSG_WriteByte((a), svc_updatestatubyte);\
1407 MSG_WriteByte((a), (b));\
1408 MSG_WriteByte((a), (c));\
1412 MSG_WriteByte((a), svc_updatestat);\
1413 MSG_WriteByte((a), (b));\
1414 MSG_WriteLong((a), (c));\
1418 void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1430 if(!vm_autosentstats)
1433 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);
1435 for(i=0; i<vm_autosentstats_last+1 ;i++)
1437 if(!vm_autosentstats[i].type)
1439 switch(vm_autosentstats[i].type)
1443 t = PRVM_E_STRING(ent, vm_autosentstats[i].fieldoffset);
1451 stats[i+32] = si[0];
1452 stats[i+33] = si[1];
1453 stats[i+34] = si[2];
1454 stats[i+35] = si[3];
1458 VM_SENDSTAT(msg, i+32, si[0]);
1459 VM_SENDSTAT(msg, i+33, si[1]);
1460 VM_SENDSTAT(msg, i+34, si[2]);
1461 VM_SENDSTAT(msg, i+35, si[3]);
1467 k.f = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1468 k.i = LittleLong (k.i);
1472 VM_SENDSTAT(msg, i+32, k.i);
1476 v = (int)PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1480 VM_SENDSTAT(msg, i+32, v);
1488 // void(float index, float type, .void field) SV_AddStat = #470;
1489 // Set up an auto-sent player stat.
1490 // Client's get thier own fields sent to them. Index may not be less than 32.
1491 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1492 // 1: string (4 stats carrying a total of 16 charactures)
1493 // 2: float (one stat, float converted to an integer for transportation)
1494 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1495 void PF_SV_AddStat (void)
1500 if(!vm_autosentstats)
1502 vm_autosentstats = (autosentstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(autosentstat_t));
1503 if(!vm_autosentstats)
1505 Con_Printf("PF_SV_AddStat: not enough memory\n");
1509 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1510 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1511 off = PRVM_G_INT (OFS_PARM2);
1516 Con_Printf("PF_SV_AddStat: index may not be less than 32\n");
1519 if(i >= (MAX_CL_STATS-32))
1521 Con_Printf("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1524 if(i > (MAX_CL_STATS-32-4) && type == 1)
1526 Con_Printf("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1529 vm_autosentstats[i].type = type;
1530 vm_autosentstats[i].fieldoffset = off;
1531 if(vm_autosentstats_last < i)
1532 vm_autosentstats_last = i;
1539 copies data from one entity to another
1541 copyentity(src, dst)
1544 void PF_copyentity (void)
1546 prvm_edict_t *in, *out;
1547 in = PRVM_G_EDICT(OFS_PARM0);
1548 if (in == prog->edicts)
1549 PF_WARNING("copyentity: can not read world entity\n");
1550 if (in->priv.server->free)
1551 PF_WARNING("copyentity: can not read free entity\n");
1552 out = PRVM_G_EDICT(OFS_PARM1);
1553 if (out == prog->edicts)
1554 PF_WARNING("copyentity: can not modify world entity\n");
1555 if (out->priv.server->free)
1556 PF_WARNING("copyentity: can not modify free entity\n");
1557 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1565 sets the color of a client and broadcasts the update to all connected clients
1567 setcolor(clientent, value)
1570 void PF_setcolor (void)
1576 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1577 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1579 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1581 Con_Print("tried to setcolor a non-client\n");
1585 client = svs.clients + entnum-1;
1588 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1590 client->edict->fields.server->team = (i & 15) + 1;
1593 if (client->old_colors != client->colors)
1595 client->old_colors = client->colors;
1596 // send notification to all clients
1597 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1598 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1599 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1607 effect(origin, modelname, startframe, framecount, framerate)
1610 void PF_effect (void)
1614 s = PRVM_G_STRING(OFS_PARM1);
1616 PF_WARNING("effect: no model specified\n");
1618 i = SV_ModelIndex(s, 1);
1620 PF_WARNING("effect: model not precached\n");
1621 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));
1624 void PF_te_blood (void)
1626 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1628 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1629 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1631 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1632 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1633 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1635 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1636 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1637 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1639 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1642 void PF_te_bloodshower (void)
1644 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1646 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1647 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1649 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1650 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1651 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1653 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1654 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1655 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1657 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1659 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1662 void PF_te_explosionrgb (void)
1664 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1665 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1667 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1668 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1669 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1671 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1672 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1673 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1676 void PF_te_particlecube (void)
1678 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1680 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1681 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1683 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1684 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1685 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1687 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1688 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1689 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1691 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1692 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1693 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1695 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1697 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1698 // gravity true/false
1699 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1701 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1704 void PF_te_particlerain (void)
1706 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1708 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1709 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1711 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1712 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1713 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1715 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1716 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1717 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1719 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1720 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1721 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1723 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1725 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1728 void PF_te_particlesnow (void)
1730 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1732 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1733 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1735 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1736 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1737 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1739 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1740 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1741 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1743 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1744 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1745 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1747 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1749 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1752 void PF_te_spark (void)
1754 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1756 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1757 MSG_WriteByte(&sv.datagram, TE_SPARK);
1759 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1760 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1761 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1763 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1764 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1765 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1767 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1770 void PF_te_gunshotquad (void)
1772 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1773 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1775 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1776 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1777 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1780 void PF_te_spikequad (void)
1782 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1783 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1785 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1786 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1787 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1790 void PF_te_superspikequad (void)
1792 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1793 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1795 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1796 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1797 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1800 void PF_te_explosionquad (void)
1802 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1803 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1805 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1810 void PF_te_smallflash (void)
1812 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1813 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1815 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1816 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1817 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1820 void PF_te_customflash (void)
1822 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1824 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1825 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1827 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1828 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1831 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1833 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1835 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1836 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1837 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1840 void PF_te_gunshot (void)
1842 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1843 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1845 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1847 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1850 void PF_te_spike (void)
1852 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1853 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1855 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1856 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1857 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1860 void PF_te_superspike (void)
1862 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1863 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1865 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1866 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1870 void PF_te_explosion (void)
1872 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1873 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1875 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1876 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1877 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1880 void PF_te_tarexplosion (void)
1882 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1883 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1885 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1886 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1887 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1890 void PF_te_wizspike (void)
1892 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1893 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1895 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1896 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1900 void PF_te_knightspike (void)
1902 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1903 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1910 void PF_te_lavasplash (void)
1912 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1913 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1915 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1916 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1917 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1920 void PF_te_teleport (void)
1922 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1923 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1925 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1926 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1930 void PF_te_explosion2 (void)
1932 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1933 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1936 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1939 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
1940 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
1943 void PF_te_lightning1 (void)
1945 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1946 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
1948 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1950 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1952 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1954 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1955 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1959 void PF_te_lightning2 (void)
1961 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1962 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
1964 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1970 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1972 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1975 void PF_te_lightning3 (void)
1977 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1978 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
1980 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1983 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1984 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1991 void PF_te_beam (void)
1993 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1994 MSG_WriteByte(&sv.datagram, TE_BEAM);
1996 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1998 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1999 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2000 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2002 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2004 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2007 void PF_te_plasmaburn (void)
2009 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2010 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2011 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2012 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2016 void PF_te_flamejet (void)
2018 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2019 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2021 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2022 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2023 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2025 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2026 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2029 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2032 void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2035 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2037 bestdist = 1000000000;
2039 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2041 // clip original point to each triangle of the surface and find the
2042 // triangle that is closest
2043 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2044 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2045 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2046 TriangleNormal(v[0], v[1], v[2], facenormal);
2047 VectorNormalize(facenormal);
2048 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2049 VectorMA(p, offsetdist, facenormal, temp);
2050 for (j = 0, k = 2;j < 3;k = j, j++)
2052 VectorSubtract(v[k], v[j], edgenormal);
2053 CrossProduct(edgenormal, facenormal, sidenormal);
2054 VectorNormalize(sidenormal);
2055 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2057 VectorMA(temp, offsetdist, sidenormal, temp);
2059 dist = VectorDistance2(temp, p);
2060 if (bestdist > dist)
2063 VectorCopy(temp, out);
2068 static model_t *getmodel(prvm_edict_t *ed)
2071 if (!ed || ed->priv.server->free)
2073 modelindex = (int)ed->fields.server->modelindex;
2074 if (modelindex < 1 || modelindex >= MAX_MODELS)
2076 return sv.models[modelindex];
2079 static msurface_t *getsurface(model_t *model, int surfacenum)
2081 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2083 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2087 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2088 void PF_getsurfacenumpoints(void)
2091 msurface_t *surface;
2092 // return 0 if no such surface
2093 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2095 PRVM_G_FLOAT(OFS_RETURN) = 0;
2099 // note: this (incorrectly) assumes it is a simple polygon
2100 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2102 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2103 void PF_getsurfacepoint(void)
2107 msurface_t *surface;
2109 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2110 ed = PRVM_G_EDICT(OFS_PARM0);
2111 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2113 // note: this (incorrectly) assumes it is a simple polygon
2114 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2115 if (pointnum < 0 || pointnum >= surface->num_vertices)
2117 // FIXME: implement rotation/scaling
2118 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2120 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2121 void PF_getsurfacenormal(void)
2124 msurface_t *surface;
2126 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2127 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2129 // FIXME: implement rotation/scaling
2130 // note: this (incorrectly) assumes it is a simple polygon
2131 // note: this only returns the first triangle, so it doesn't work very
2132 // well for curved surfaces or arbitrary meshes
2133 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);
2134 VectorNormalize(normal);
2135 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2137 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2138 void PF_getsurfacetexture(void)
2141 msurface_t *surface;
2142 PRVM_G_INT(OFS_RETURN) = 0;
2143 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2145 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
2147 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2148 void PF_getsurfacenearpoint(void)
2150 int surfacenum, best;
2152 vec_t dist, bestdist;
2155 msurface_t *surface;
2157 PRVM_G_FLOAT(OFS_RETURN) = -1;
2158 ed = PRVM_G_EDICT(OFS_PARM0);
2159 point = PRVM_G_VECTOR(OFS_PARM1);
2161 if (!ed || ed->priv.server->free)
2163 model = getmodel(ed);
2164 if (!model || !model->num_surfaces)
2167 // FIXME: implement rotation/scaling
2168 VectorSubtract(point, ed->fields.server->origin, p);
2170 bestdist = 1000000000;
2171 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2173 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2174 // first see if the nearest point on the surface's box is closer than the previous match
2175 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2176 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2177 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2178 dist = VectorLength2(clipped);
2179 if (dist < bestdist)
2181 // it is, check the nearest point on the actual geometry
2182 clippointtosurface(model, surface, p, clipped);
2183 VectorSubtract(clipped, p, clipped);
2184 dist += VectorLength2(clipped);
2185 if (dist < bestdist)
2187 // that's closer too, store it as the best match
2193 PRVM_G_FLOAT(OFS_RETURN) = best;
2195 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2196 void PF_getsurfaceclippedpoint(void)
2200 msurface_t *surface;
2202 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2203 ed = PRVM_G_EDICT(OFS_PARM0);
2204 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2206 // FIXME: implement rotation/scaling
2207 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2208 clippointtosurface(model, surface, p, out);
2209 // FIXME: implement rotation/scaling
2210 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2213 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2214 //this function originally written by KrimZon, made shorter by LordHavoc
2215 void PF_clientcommand (void)
2217 client_t *temp_client;
2220 //find client for this entity
2221 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2222 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2224 Con_Print("PF_clientcommand: entity is not a client\n");
2228 temp_client = host_client;
2229 host_client = svs.clients + i;
2230 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2231 host_client = temp_client;
2234 //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)
2235 void PF_setattachment (void)
2237 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2238 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2239 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2244 if (e == prog->edicts)
2245 PF_WARNING("setattachment: can not modify world entity\n");
2246 if (e->priv.server->free)
2247 PF_WARNING("setattachment: can not modify free entity\n");
2249 if (tagentity == NULL)
2250 tagentity = prog->edicts;
2252 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2254 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2256 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2259 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2261 modelindex = (int)tagentity->fields.server->modelindex;
2262 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2264 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2266 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);
2269 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));
2273 /////////////////////////////////////////
2274 // DP_MD3_TAGINFO extension coded by VorteX
2276 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2281 i = (int)e->fields.server->modelindex;
2282 if (i < 1 || i >= MAX_MODELS)
2284 model = sv.models[i];
2286 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2289 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2291 float scale = PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float;
2295 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);
2297 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);
2300 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2306 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2307 && (model = sv.models[(int)ent->fields.server->modelindex])
2308 && model->animscenes)
2310 // if model has wrong frame, engine automatically switches to model first frame
2311 frame = (int)ent->fields.server->frame;
2312 if (frame < 0 || frame >= model->numframes)
2314 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2316 *out = identitymatrix;
2320 // Warnings/errors code:
2321 // 0 - normal (everything all-right)
2324 // 3 - null or non-precached model
2325 // 4 - no tags with requested index
2326 // 5 - runaway loop at attachment chain
2327 extern cvar_t cl_bob;
2328 extern cvar_t cl_bobcycle;
2329 extern cvar_t cl_bobup;
2330 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2334 int modelindex, attachloop;
2335 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2338 *out = identitymatrix; // warnings and errors return identical matrix
2340 if (ent == prog->edicts)
2342 if (ent->priv.server->free)
2345 modelindex = (int)ent->fields.server->modelindex;
2346 if (modelindex <= 0 || modelindex > MAX_MODELS)
2349 model = sv.models[modelindex];
2351 tagmatrix = identitymatrix;
2352 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2356 if (attachloop >= 256) // prevent runaway looping
2358 // apply transformation by child's tagindex on parent entity and then
2359 // by parent entity itself
2360 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2361 if (ret && attachloop == 0)
2363 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2364 SV_GetEntityMatrix(ent, &entitymatrix, false);
2365 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2366 // next iteration we process the parent entity
2367 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2369 tagindex = (int)PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
2370 ent = PRVM_EDICT_NUM(val->edict);
2377 // RENDER_VIEWMODEL magic
2378 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2380 Matrix4x4_Copy(&tagmatrix, out);
2381 ent = PRVM_EDICT_NUM(val->edict);
2383 SV_GetEntityMatrix(ent, &entitymatrix, true);
2384 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2387 // Cl_bob, ported from rendering code
2388 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2391 // LordHavoc: this code is *weird*, but not replacable (I think it
2392 // should be done in QC on the server, but oh well, quake is quake)
2393 // LordHavoc: figured out bobup: the time at which the sin is at 180
2394 // degrees (which allows lengthening or squishing the peak or valley)
2395 cycle = sv.time/cl_bobcycle.value;
2396 cycle -= (int)cycle;
2397 if (cycle < cl_bobup.value)
2398 cycle = sin(M_PI * cycle / cl_bobup.value);
2400 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2401 // bob is proportional to velocity in the xy plane
2402 // (don't count Z, or jumping messes it up)
2403 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;
2404 bob = bob*0.3 + bob*0.7*cycle;
2405 out->m[2][3] += bound(-7, bob, 4);
2412 //float(entity ent, string tagname) gettagindex;
2414 void PF_gettagindex (void)
2416 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2417 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2418 int modelindex, tag_index;
2420 if (ent == prog->edicts)
2421 PF_WARNING("gettagindex: can't affect world entity\n");
2422 if (ent->priv.server->free)
2423 PF_WARNING("gettagindex: can't affect free entity\n");
2425 modelindex = (int)ent->fields.server->modelindex;
2427 if (modelindex <= 0 || modelindex > MAX_MODELS)
2428 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2431 tag_index = SV_GetTagIndex(ent, tag_name);
2433 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2435 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2438 //vector(entity ent, float tagindex) gettaginfo;
2439 void PF_gettaginfo (void)
2441 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2442 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2443 matrix4x4_t tag_matrix;
2446 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2447 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2452 PF_WARNING("gettagindex: can't affect world entity\n");
2455 PF_WARNING("gettagindex: can't affect free entity\n");
2458 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2461 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2464 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2469 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2470 void PF_dropclient (void)
2473 client_t *oldhostclient;
2474 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2475 if (clientnum < 0 || clientnum >= svs.maxclients)
2476 PF_WARNING("dropclient: not a client\n");
2477 if (!svs.clients[clientnum].active)
2478 PF_WARNING("dropclient: that client slot is not connected\n");
2479 oldhostclient = host_client;
2480 host_client = svs.clients + clientnum;
2481 SV_DropClient(false);
2482 host_client = oldhostclient;
2485 //entity() spawnclient (DP_SV_BOTCLIENT)
2486 void PF_spawnclient (void)
2490 prog->xfunction->builtinsprofile += 2;
2492 for (i = 0;i < svs.maxclients;i++)
2494 if (!svs.clients[i].active)
2496 prog->xfunction->builtinsprofile += 100;
2497 SV_ConnectClient (i, NULL);
2498 // this has to be set or else ClientDisconnect won't be called
2499 // we assume the qc will call ClientConnect...
2500 svs.clients[i].clientconnectcalled = true;
2501 ed = PRVM_EDICT_NUM(i + 1);
2505 VM_RETURN_EDICT(ed);
2508 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2509 void PF_clienttype (void)
2512 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2513 if (clientnum < 0 || clientnum >= svs.maxclients)
2514 PRVM_G_FLOAT(OFS_RETURN) = 3;
2515 else if (!svs.clients[clientnum].active)
2516 PRVM_G_FLOAT(OFS_RETURN) = 0;
2517 else if (svs.clients[clientnum].netconnection)
2518 PRVM_G_FLOAT(OFS_RETURN) = 1;
2520 PRVM_G_FLOAT(OFS_RETURN) = 2;
2523 void PF_edict_num (void)
2525 VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0)));
2528 prvm_builtin_t vm_sv_builtins[] = {
2530 PF_makevectors, // #1 void(vector ang) makevectors
2531 PF_setorigin, // #2 void(entity e, vector o) setorigin
2532 PF_setmodel, // #3 void(entity e, string m) setmodel
2533 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2534 NULL, // #5 void(entity e, vector min, vector max) setabssize
2535 VM_break, // #6 void() break
2536 VM_random, // #7 float() random
2537 PF_sound, // #8 void(entity e, float chan, string samp) sound
2538 VM_normalize, // #9 vector(vector v) normalize
2539 VM_error, // #10 void(string e) error
2540 VM_objerror, // #11 void(string e) objerror
2541 VM_vlen, // #12 float(vector v) vlen
2542 VM_vectoyaw, // #13 float(vector v) vectoyaw
2543 VM_spawn, // #14 entity() spawn
2544 VM_remove, // #15 void(entity e) remove
2545 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2546 PF_checkclient, // #17 entity() clientlist
2547 VM_find, // #18 entity(entity start, .string fld, string match) find
2548 PF_precache_sound, // #19 void(string s) precache_sound
2549 PF_precache_model, // #20 void(string s) precache_model
2550 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2551 PF_findradius, // #22 entity(vector org, float rad) findradius
2552 VM_bprint, // #23 void(string s) bprint
2553 PF_sprint, // #24 void(entity client, string s) sprint
2554 VM_dprint, // #25 void(string s) dprint
2555 VM_ftos, // #26 void(string s) ftos
2556 VM_vtos, // #27 void(string s) vtos
2557 VM_coredump, // #28 void() coredump
2558 VM_traceon, // #29 void() traceon
2559 VM_traceoff, // #30 void() traceoff
2560 VM_eprint, // #31 void(entity e) eprint
2561 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2563 PF_droptofloor, // #34 float() droptofloor
2564 PF_lightstyle, // #35 void(float style, string value) lightstyle
2565 VM_rint, // #36 float(float v) rint
2566 VM_floor, // #37 float(float v) floor
2567 VM_ceil, // #38 float(float v) ceil
2569 PF_checkbottom, // #40 float(entity e) checkbottom
2570 PF_pointcontents, // #41 float(vector v) pointcontents
2572 VM_fabs, // #43 float(float f) fabs
2573 PF_aim, // #44 vector(entity e, float speed) aim
2574 VM_cvar, // #45 float(string s) cvar
2575 VM_localcmd, // #46 void(string s) localcmd
2576 VM_nextent, // #47 entity(entity e) nextent
2577 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2578 PF_changeyaw, // #49 void() ChangeYaw
2580 VM_vectoangles, // #51 vector(vector v) vectoangles
2581 PF_WriteByte, // #52 void(float to, float f) WriteByte
2582 PF_WriteChar, // #53 void(float to, float f) WriteChar
2583 PF_WriteShort, // #54 void(float to, float f) WriteShort
2584 PF_WriteLong, // #55 void(float to, float f) WriteLong
2585 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2586 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2587 PF_WriteString, // #58 void(float to, string s) WriteString
2588 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2589 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2590 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2591 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2592 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2593 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2594 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2596 SV_MoveToGoal, // #67 void(float step) movetogoal
2597 PF_precache_file, // #68 string(string s) precache_file
2598 PF_makestatic, // #69 void(entity e) makestatic
2599 VM_changelevel, // #70 void(string s) changelevel
2601 VM_cvar_set, // #72 void(string var, string val) cvar_set
2602 PF_centerprint, // #73 void(entity client, strings) centerprint
2603 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2604 PF_precache_model, // #75 string(string s) precache_model2
2605 PF_precache_sound, // #76 string(string s) precache_sound2
2606 PF_precache_file, // #77 string(string s) precache_file2
2607 PF_setspawnparms, // #78 void(entity e) setspawnparms
2610 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2619 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2620 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2621 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2622 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2623 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2624 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2625 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2626 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2627 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2628 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2639 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2640 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2641 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2642 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2643 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2644 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2645 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2646 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2647 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2648 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2649 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2650 // FTEQW range #200-#299
2669 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2679 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2680 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2681 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2682 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2683 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2684 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2685 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2686 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2687 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2688 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2689 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2690 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2691 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2692 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2693 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2694 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2695 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2696 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2697 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2698 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2699 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2700 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2701 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2702 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2703 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2704 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2705 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2706 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2707 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2708 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2709 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2710 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2711 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2712 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2713 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2714 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2715 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2716 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2717 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2718 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2719 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2720 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2721 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2722 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2723 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2724 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2725 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2726 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2727 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2728 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2729 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2730 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2731 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2732 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2733 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2734 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2735 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2736 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2737 PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2739 PF_edict_num, // #459 entity(float num) (??)
2740 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2741 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2742 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2743 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2744 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2745 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2746 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2747 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2748 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2749 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2750 PF_SV_AddStat, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2760 e10, e10 // #480-499 (LordHavoc)
2763 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2765 void VM_SV_Cmd_Init(void)
2770 void VM_SV_Cmd_Reset(void)