3 //============================================================================
6 cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2", "maximum cosine angle for quake's vertical autoaim, a value above 1 completely disables the autoaim, quake used 0.93"}; //"0.93"}; // LordHavoc: disabled autoaim by default
9 char *vm_sv_extensions =
11 "DP_CON_ALIASPARAMETERS "
30 "DP_ENT_CUSTOMCOLORMAP "
31 "DP_ENT_EXTERIORMODELTOCLIENT "
33 "DP_ENT_LOWPRECISION "
36 "DP_GFX_EXTERNALTEXTURES "
37 "DP_GFX_EXTERNALTEXTURES_PERMAP "
39 "DP_GFX_QUAKE3MODELTAGS "
43 "DP_HALFLIFE_MAP_CVAR "
49 "DP_MOVETYPEBOUNCEMISSILE "
51 "DP_QC_ASINACOSATANATAN2TAN "
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 "
70 "DP_QC_STRINGCOLORFUNCTIONS "
73 "DP_QC_TRACE_MOVETYPE_HITMODEL "
74 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
75 "DP_QC_VECTORVECTORS "
81 "DP_SND_DIRECTIONLESSATTNNONE "
90 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
91 "DP_SV_DRAWONLYTOCLIENT "
94 "DP_SV_ENTITYCONTENTSTRANSITION "
95 "DP_SV_NODRAWTOCLIENT "
97 "DP_SV_PLAYERPHYSICS "
98 "DP_SV_PRECACHEANYTIME "
100 "DP_SV_ROTATINGBMODEL "
103 "DP_SV_WRITEUNTERMINATEDSTRING "
107 "DP_TE_EXPLOSIONRGB "
109 "DP_TE_PARTICLECUBE "
110 "DP_TE_PARTICLERAIN "
111 "DP_TE_PARTICLESNOW "
113 "DP_TE_QUADEFFECTS1 "
116 "DP_TE_STANDARDEFFECTBUILTINS "
117 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
120 //"EXT_CSQC " // not ready yet
122 "KRIMZON_SV_PARSECLIENTCOMMAND "
126 "PRYDON_CLIENTCURSOR "
127 "TENEBRAE_GFX_DLIGHTS "
129 "NEXUIZ_PLAYERMODEL "
136 Writes new values for v_forward, v_up, and v_right based on angles
140 void PF_makevectors (void)
142 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
149 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.
151 setorigin (entity, origin)
154 void PF_setorigin (void)
159 e = PRVM_G_EDICT(OFS_PARM0);
160 if (e == prog->edicts)
162 VM_Warning("setorigin: can not modify world entity\n");
165 if (e->priv.server->free)
167 VM_Warning("setorigin: can not modify free entity\n");
170 org = PRVM_G_VECTOR(OFS_PARM1);
171 VectorCopy (org, e->fields.server->origin);
172 SV_LinkEdict (e, false);
176 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
180 for (i=0 ; i<3 ; i++)
182 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
184 // set derived values
185 VectorCopy (min, e->fields.server->mins);
186 VectorCopy (max, e->fields.server->maxs);
187 VectorSubtract (max, min, e->fields.server->size);
189 SV_LinkEdict (e, false);
196 the size box is rotated by the current angle
197 LordHavoc: no it isn't...
199 setsize (entity, minvector, maxvector)
202 void PF_setsize (void)
207 e = PRVM_G_EDICT(OFS_PARM0);
208 if (e == prog->edicts)
210 VM_Warning("setsize: can not modify world entity\n");
213 if (e->priv.server->free)
215 VM_Warning("setsize: can not modify free entity\n");
218 min = PRVM_G_VECTOR(OFS_PARM1);
219 max = PRVM_G_VECTOR(OFS_PARM2);
220 SetMinMaxSize (e, min, max, false);
228 setmodel(entity, model)
231 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
232 void PF_setmodel (void)
238 e = PRVM_G_EDICT(OFS_PARM0);
239 if (e == prog->edicts)
241 VM_Warning("setmodel: can not modify world entity\n");
244 if (e->priv.server->free)
246 VM_Warning("setmodel: can not modify free entity\n");
249 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
250 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
251 e->fields.server->modelindex = i;
257 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
258 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
260 SetMinMaxSize (e, quakemins, quakemaxs, true);
263 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
270 single print to a specific client
272 sprint(clientent, value)
275 void PF_sprint (void)
279 char string[VM_STRINGTEMP_LENGTH];
281 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
283 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
285 VM_Warning("tried to centerprint to a non-client\n");
289 client = svs.clients + entnum-1;
290 if (!client->netconnection)
293 VM_VarString(1, string, sizeof(string));
294 MSG_WriteChar(&client->netconnection->message,svc_print);
295 MSG_WriteString(&client->netconnection->message, string);
303 single print to a specific client
305 centerprint(clientent, value)
308 void PF_centerprint (void)
312 char string[VM_STRINGTEMP_LENGTH];
314 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
316 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
318 VM_Warning("tried to centerprint to a non-client\n");
322 client = svs.clients + entnum-1;
323 if (!client->netconnection)
326 VM_VarString(1, string, sizeof(string));
327 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
328 MSG_WriteString(&client->netconnection->message, string);
335 particle(origin, color, count)
338 void PF_particle (void)
344 org = PRVM_G_VECTOR(OFS_PARM0);
345 dir = PRVM_G_VECTOR(OFS_PARM1);
346 color = PRVM_G_FLOAT(OFS_PARM2);
347 count = PRVM_G_FLOAT(OFS_PARM3);
348 SV_StartParticle (org, dir, (int)color, (int)count);
358 void PF_ambientsound (void)
362 float vol, attenuation;
365 pos = PRVM_G_VECTOR (OFS_PARM0);
366 samp = PRVM_G_STRING(OFS_PARM1);
367 vol = PRVM_G_FLOAT(OFS_PARM2);
368 attenuation = PRVM_G_FLOAT(OFS_PARM3);
370 // check to see if samp was properly precached
371 soundnum = SV_SoundIndex(samp, 1);
379 // add an svc_spawnambient command to the level signon packet
382 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
384 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
386 MSG_WriteVector(&sv.signon, pos, sv.protocol);
389 MSG_WriteShort (&sv.signon, soundnum);
391 MSG_WriteByte (&sv.signon, soundnum);
393 MSG_WriteByte (&sv.signon, (int)(vol*255));
394 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
402 Each entity can have eight independant sound sources, like voice,
405 Channel 0 is an auto-allocate channel, the others override anything
406 already running on that entity/channel pair.
408 An attenuation of 0 will play full volume everywhere in the level.
409 Larger attenuations will drop off.
417 prvm_edict_t *entity;
421 entity = PRVM_G_EDICT(OFS_PARM0);
422 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
423 sample = PRVM_G_STRING(OFS_PARM2);
424 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
425 attenuation = PRVM_G_FLOAT(OFS_PARM4);
427 if (volume < 0 || volume > 255)
429 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
433 if (attenuation < 0 || attenuation > 4)
435 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
439 if (channel < 0 || channel > 7)
441 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
445 SV_StartSound (entity, channel, sample, volume, attenuation);
452 Used for use tracing and shot targeting
453 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
454 if the tryents flag is set.
456 traceline (vector1, vector2, tryents)
459 void PF_traceline (void)
467 prog->xfunction->builtinsprofile += 30;
469 v1 = PRVM_G_VECTOR(OFS_PARM0);
470 v2 = PRVM_G_VECTOR(OFS_PARM1);
471 move = (int)PRVM_G_FLOAT(OFS_PARM2);
472 ent = PRVM_G_EDICT(OFS_PARM3);
474 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]))
475 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));
477 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
479 prog->globals.server->trace_allsolid = trace.allsolid;
480 prog->globals.server->trace_startsolid = trace.startsolid;
481 prog->globals.server->trace_fraction = trace.fraction;
482 prog->globals.server->trace_inwater = trace.inwater;
483 prog->globals.server->trace_inopen = trace.inopen;
484 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
485 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
486 prog->globals.server->trace_plane_dist = trace.plane.dist;
488 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
490 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
491 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
492 val->_float = trace.startsupercontents;
493 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
494 val->_float = trace.hitsupercontents;
495 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
496 val->_float = trace.hitq3surfaceflags;
497 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
499 if (trace.hittexture)
501 char *s = VM_GetTempString();
502 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
503 val->string = PRVM_SetEngineString(s);
515 Used for use tracing and shot targeting
516 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
517 if the tryents flag is set.
519 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
522 // LordHavoc: added this for my own use, VERY useful, similar to traceline
523 void PF_tracebox (void)
525 float *v1, *v2, *m1, *m2;
531 prog->xfunction->builtinsprofile += 30;
533 v1 = PRVM_G_VECTOR(OFS_PARM0);
534 m1 = PRVM_G_VECTOR(OFS_PARM1);
535 m2 = PRVM_G_VECTOR(OFS_PARM2);
536 v2 = PRVM_G_VECTOR(OFS_PARM3);
537 move = (int)PRVM_G_FLOAT(OFS_PARM4);
538 ent = PRVM_G_EDICT(OFS_PARM5);
540 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]))
541 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));
543 trace = SV_Move (v1, m1, m2, v2, move, ent);
545 prog->globals.server->trace_allsolid = trace.allsolid;
546 prog->globals.server->trace_startsolid = trace.startsolid;
547 prog->globals.server->trace_fraction = trace.fraction;
548 prog->globals.server->trace_inwater = trace.inwater;
549 prog->globals.server->trace_inopen = trace.inopen;
550 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
551 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
552 prog->globals.server->trace_plane_dist = trace.plane.dist;
554 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
556 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
557 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
558 val->_float = trace.startsupercontents;
559 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
560 val->_float = trace.hitsupercontents;
561 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
562 val->_float = trace.hitq3surfaceflags;
563 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
565 if (trace.hittexture)
567 char *s = VM_GetTempString();
568 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
569 val->string = PRVM_SetEngineString(s);
576 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
577 void PF_tracetoss (void)
581 prvm_edict_t *ignore;
584 prog->xfunction->builtinsprofile += 600;
586 ent = PRVM_G_EDICT(OFS_PARM0);
587 if (ent == prog->edicts)
589 VM_Warning("tracetoss: can not use world entity\n");
592 ignore = PRVM_G_EDICT(OFS_PARM1);
594 trace = SV_Trace_Toss (ent, ignore);
596 prog->globals.server->trace_allsolid = trace.allsolid;
597 prog->globals.server->trace_startsolid = trace.startsolid;
598 prog->globals.server->trace_fraction = trace.fraction;
599 prog->globals.server->trace_inwater = trace.inwater;
600 prog->globals.server->trace_inopen = trace.inopen;
601 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
602 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
603 prog->globals.server->trace_plane_dist = trace.plane.dist;
605 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
607 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
608 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
609 val->_float = trace.startsupercontents;
610 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
611 val->_float = trace.hitsupercontents;
612 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
613 val->_float = trace.hitq3surfaceflags;
614 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
616 if (trace.hittexture)
618 char *s = VM_GetTempString();
619 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
620 val->string = PRVM_SetEngineString(s);
632 Returns true if the given entity can move to the given position from it's
633 current position by walking or rolling.
635 scalar checkpos (entity, vector)
638 void PF_checkpos (void)
642 //============================================================================
645 unsigned char checkpvs[MAX_MAP_LEAFS/8];
647 int PF_newcheckclient (int check)
653 // cycle to the next one
655 check = bound(1, check, svs.maxclients);
656 if (check == svs.maxclients)
664 prog->xfunction->builtinsprofile++;
666 if (i == svs.maxclients+1)
668 // look up the client's edict
669 ent = PRVM_EDICT_NUM(i);
670 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
671 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
673 // found a valid client (possibly the same one again)
677 // get the PVS for the entity
678 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
680 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
681 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
690 Returns a client (or object that has a client enemy) that would be a
693 If there is more than one valid option, they are cycled each frame
695 If (self.origin + self.viewofs) is not in the PVS of the current target,
696 it is not returned at all.
701 int c_invis, c_notvis;
702 void PF_checkclient (void)
704 prvm_edict_t *ent, *self;
707 // find a new check if on a new frame
708 if (sv.time - sv.lastchecktime >= 0.1)
710 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
711 sv.lastchecktime = sv.time;
714 // return check if it might be visible
715 ent = PRVM_EDICT_NUM(sv.lastcheck);
716 if (ent->priv.server->free || ent->fields.server->health <= 0)
718 VM_RETURN_EDICT(prog->edicts);
722 // if current entity can't possibly see the check entity, return 0
723 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
724 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
725 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
728 VM_RETURN_EDICT(prog->edicts);
732 // might be able to see it
734 VM_RETURN_EDICT(ent);
737 //============================================================================
744 Sends text over to the client's execution buffer
746 stuffcmd (clientent, value, ...)
749 void PF_stuffcmd (void)
753 char string[VM_STRINGTEMP_LENGTH];
755 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
756 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
758 VM_Warning("Can't stuffcmd to a non-client\n");
762 VM_VarString(1, string, sizeof(string));
765 host_client = svs.clients + entnum-1;
766 Host_ClientCommands ("%s", string);
774 Returns a chain of entities that have origins within a spherical area
776 findradius (origin, radius)
779 void PF_findradius (void)
781 prvm_edict_t *ent, *chain;
782 vec_t radius, radius2;
783 vec3_t org, eorg, mins, maxs;
786 prvm_edict_t *touchedicts[MAX_EDICTS];
788 chain = (prvm_edict_t *)prog->edicts;
790 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
791 radius = PRVM_G_FLOAT(OFS_PARM1);
792 radius2 = radius * radius;
794 mins[0] = org[0] - (radius + 1);
795 mins[1] = org[1] - (radius + 1);
796 mins[2] = org[2] - (radius + 1);
797 maxs[0] = org[0] + (radius + 1);
798 maxs[1] = org[1] + (radius + 1);
799 maxs[2] = org[2] + (radius + 1);
800 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
801 if (numtouchedicts > MAX_EDICTS)
803 // this never happens
804 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
805 numtouchedicts = MAX_EDICTS;
807 for (i = 0;i < numtouchedicts;i++)
809 ent = touchedicts[i];
810 prog->xfunction->builtinsprofile++;
811 // Quake did not return non-solid entities but darkplaces does
812 // (note: this is the reason you can't blow up fallen zombies)
813 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
815 // LordHavoc: compare against bounding box rather than center so it
816 // doesn't miss large objects, and use DotProduct instead of Length
817 // for a major speedup
818 VectorSubtract(org, ent->fields.server->origin, eorg);
819 if (sv_gameplayfix_findradiusdistancetobox.integer)
821 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
822 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
823 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
826 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
827 if (DotProduct(eorg, eorg) < radius2)
829 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
834 VM_RETURN_EDICT(chain);
837 void PF_precache_file (void)
838 { // precache_file is only used to copy files with qcc, it does nothing
839 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
843 void PF_precache_sound (void)
845 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
846 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
849 void PF_precache_model (void)
851 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
852 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
859 float(float yaw, float dist) walkmove
862 void PF_walkmove (void)
870 // assume failure if it returns early
871 PRVM_G_FLOAT(OFS_RETURN) = 0;
873 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
874 if (ent == prog->edicts)
876 VM_Warning("walkmove: can not modify world entity\n");
879 if (ent->priv.server->free)
881 VM_Warning("walkmove: can not modify free entity\n");
884 yaw = PRVM_G_FLOAT(OFS_PARM0);
885 dist = PRVM_G_FLOAT(OFS_PARM1);
887 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
890 yaw = yaw*M_PI*2 / 360;
892 move[0] = cos(yaw)*dist;
893 move[1] = sin(yaw)*dist;
896 // save program state, because SV_movestep may call other progs
897 oldf = prog->xfunction;
898 oldself = prog->globals.server->self;
900 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
903 // restore program state
904 prog->xfunction = oldf;
905 prog->globals.server->self = oldself;
915 void PF_droptofloor (void)
921 // assume failure if it returns early
922 PRVM_G_FLOAT(OFS_RETURN) = 0;
924 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
925 if (ent == prog->edicts)
927 VM_Warning("droptofloor: can not modify world entity\n");
930 if (ent->priv.server->free)
932 VM_Warning("droptofloor: can not modify free entity\n");
936 VectorCopy (ent->fields.server->origin, end);
939 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
941 if (trace.fraction != 1)
943 VectorCopy (trace.endpos, ent->fields.server->origin);
944 SV_LinkEdict (ent, false);
945 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
946 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
947 PRVM_G_FLOAT(OFS_RETURN) = 1;
948 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
949 ent->priv.server->suspendedinairflag = true;
957 void(float style, string value) lightstyle
960 void PF_lightstyle (void)
967 style = (int)PRVM_G_FLOAT(OFS_PARM0);
968 val = PRVM_G_STRING(OFS_PARM1);
970 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
971 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
974 // change the string in sv
975 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
977 // send message to all clients on this server
978 if (sv.state != ss_active)
981 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
983 if (client->active && client->netconnection)
985 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
986 MSG_WriteChar (&client->netconnection->message,style);
987 MSG_WriteString (&client->netconnection->message, val);
997 void PF_checkbottom (void)
999 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1007 void PF_pointcontents (void)
1009 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1016 Pick a vector for the player to shoot along
1017 vector aim(entity, missilespeed)
1022 prvm_edict_t *ent, *check, *bestent;
1023 vec3_t start, dir, end, bestdir;
1026 float dist, bestdist;
1029 // assume failure if it returns early
1030 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1031 // if sv_aim is so high it can't possibly accept anything, skip out early
1032 if (sv_aim.value >= 1)
1035 ent = PRVM_G_EDICT(OFS_PARM0);
1036 if (ent == prog->edicts)
1038 VM_Warning("aim: can not use world entity\n");
1041 if (ent->priv.server->free)
1043 VM_Warning("aim: can not use free entity\n");
1046 speed = PRVM_G_FLOAT(OFS_PARM1);
1048 VectorCopy (ent->fields.server->origin, start);
1051 // try sending a trace straight
1052 VectorCopy (prog->globals.server->v_forward, dir);
1053 VectorMA (start, 2048, dir, end);
1054 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1055 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1056 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1058 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1063 // try all possible entities
1064 VectorCopy (dir, bestdir);
1065 bestdist = sv_aim.value;
1068 check = PRVM_NEXT_EDICT(prog->edicts);
1069 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1071 prog->xfunction->builtinsprofile++;
1072 if (check->fields.server->takedamage != DAMAGE_AIM)
1076 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1077 continue; // don't aim at teammate
1078 for (j=0 ; j<3 ; j++)
1079 end[j] = check->fields.server->origin[j]
1080 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1081 VectorSubtract (end, start, dir);
1082 VectorNormalize (dir);
1083 dist = DotProduct (dir, prog->globals.server->v_forward);
1084 if (dist < bestdist)
1085 continue; // to far to turn
1086 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1087 if (tr.ent == check)
1088 { // can shoot at this one
1096 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1097 dist = DotProduct (dir, prog->globals.server->v_forward);
1098 VectorScale (prog->globals.server->v_forward, dist, end);
1100 VectorNormalize (end);
1101 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1105 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1113 This was a major timewaster in progs, so it was converted to C
1116 void PF_changeyaw (void)
1119 float ideal, current, move, speed;
1121 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1122 if (ent == prog->edicts)
1124 VM_Warning("changeyaw: can not modify world entity\n");
1127 if (ent->priv.server->free)
1129 VM_Warning("changeyaw: can not modify free entity\n");
1132 current = ANGLEMOD(ent->fields.server->angles[1]);
1133 ideal = ent->fields.server->ideal_yaw;
1134 speed = ent->fields.server->yaw_speed;
1136 if (current == ideal)
1138 move = ideal - current;
1139 if (ideal > current)
1160 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1168 void PF_changepitch (void)
1171 float ideal, current, move, speed;
1174 ent = PRVM_G_EDICT(OFS_PARM0);
1175 if (ent == prog->edicts)
1177 VM_Warning("changepitch: can not modify world entity\n");
1180 if (ent->priv.server->free)
1182 VM_Warning("changepitch: can not modify free entity\n");
1185 current = ANGLEMOD( ent->fields.server->angles[0] );
1186 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1187 ideal = val->_float;
1190 VM_Warning("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1193 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1194 speed = val->_float;
1197 VM_Warning("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1201 if (current == ideal)
1203 move = ideal - current;
1204 if (ideal > current)
1225 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1229 ===============================================================================
1233 ===============================================================================
1236 #define MSG_BROADCAST 0 // unreliable to all
1237 #define MSG_ONE 1 // reliable to one (msg_entity)
1238 #define MSG_ALL 2 // reliable to all
1239 #define MSG_INIT 3 // write to the init string
1240 #define MSG_ENTITY 5
1242 sizebuf_t *WriteDest (void)
1247 extern sizebuf_t *sv2csqcbuf;
1249 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1253 return &sv.datagram;
1256 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1257 entnum = PRVM_NUM_FOR_EDICT(ent);
1258 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1260 VM_Warning ("WriteDest: tried to write to non-client\n");
1261 return &sv.reliable_datagram;
1264 return &svs.clients[entnum-1].netconnection->message;
1267 VM_Warning ("WriteDest: bad destination\n");
1269 return &sv.reliable_datagram;
1281 void PF_WriteByte (void)
1283 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1286 void PF_WriteChar (void)
1288 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1291 void PF_WriteShort (void)
1293 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1296 void PF_WriteLong (void)
1298 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1301 void PF_WriteAngle (void)
1303 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1306 void PF_WriteCoord (void)
1308 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1311 void PF_WriteString (void)
1313 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1316 void PF_WriteUnterminatedString (void)
1318 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1322 void PF_WriteEntity (void)
1324 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1327 //////////////////////////////////////////////////////////
1329 void PF_makestatic (void)
1334 ent = PRVM_G_EDICT(OFS_PARM0);
1335 if (ent == prog->edicts)
1337 VM_Warning("makestatic: can not modify world entity\n");
1340 if (ent->priv.server->free)
1342 VM_Warning("makestatic: can not modify free entity\n");
1347 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1352 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1353 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1354 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1358 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1359 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1360 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1363 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1364 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1365 for (i=0 ; i<3 ; i++)
1367 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1368 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1371 // throw the entity away now
1375 //=============================================================================
1382 void PF_setspawnparms (void)
1388 ent = PRVM_G_EDICT(OFS_PARM0);
1389 i = PRVM_NUM_FOR_EDICT(ent);
1390 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1392 Con_Print("tried to setspawnparms on a non-client\n");
1396 // copy spawn parms out of the client_t
1397 client = svs.clients + i-1;
1398 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1399 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1406 Returns a color vector indicating the lighting at the requested point.
1408 (Internal Operation note: actually measures the light beneath the point, just like
1409 the model lighting on the client)
1414 void PF_getlight (void)
1416 vec3_t ambientcolor, diffusecolor, diffusenormal;
1418 p = PRVM_G_VECTOR(OFS_PARM0);
1419 VectorClear(ambientcolor);
1420 VectorClear(diffusecolor);
1421 VectorClear(diffusenormal);
1422 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1423 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1424 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1427 void PF_registercvar (void)
1429 const char *name, *value;
1430 name = PRVM_G_STRING(OFS_PARM0);
1431 value = PRVM_G_STRING(OFS_PARM1);
1432 PRVM_G_FLOAT(OFS_RETURN) = 0;
1434 // first check to see if it has already been defined
1435 if (Cvar_FindVar (name))
1438 // check for overlap with a command
1439 if (Cmd_Exists (name))
1441 VM_Warning("PF_registercvar: %s is a command\n", name);
1445 Cvar_Get(name, value, 0);
1447 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1452 unsigned char type; // 1/2/8 or other value if isn't used
1456 static autosentstat_t *vm_autosentstats = NULL; //[515]: it starts from 0, not 32
1457 static int vm_autosentstats_last;
1459 void VM_AutoSentStats_Clear (void)
1461 if(vm_autosentstats)
1463 Z_Free(vm_autosentstats);
1464 vm_autosentstats = NULL;
1465 vm_autosentstats_last = -1;
1469 //[515]: add check if even bigger ? "try to use two stats, cause it's too big" ?
1470 #define VM_SENDSTAT(a,b,c)\
1473 if((c)==(unsigned char)(c))\
1475 MSG_WriteByte((a), svc_updatestatubyte);\
1476 MSG_WriteByte((a), (b));\
1477 MSG_WriteByte((a), (c));\
1481 MSG_WriteByte((a), svc_updatestat);\
1482 MSG_WriteByte((a), (b));\
1483 MSG_WriteLong((a), (c));\
1487 void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1499 if(!vm_autosentstats)
1502 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);
1504 for(i=0; i<vm_autosentstats_last+1 ;i++)
1506 if(!vm_autosentstats[i].type)
1508 switch(vm_autosentstats[i].type)
1512 t = PRVM_E_STRING(ent, vm_autosentstats[i].fieldoffset);
1520 stats[i+32] = si[0];
1521 stats[i+33] = si[1];
1522 stats[i+34] = si[2];
1523 stats[i+35] = si[3];
1527 VM_SENDSTAT(msg, i+32, si[0]);
1528 VM_SENDSTAT(msg, i+33, si[1]);
1529 VM_SENDSTAT(msg, i+34, si[2]);
1530 VM_SENDSTAT(msg, i+35, si[3]);
1536 k.f = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1537 k.i = LittleLong (k.i);
1541 VM_SENDSTAT(msg, i+32, k.i);
1545 v = (int)PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1549 VM_SENDSTAT(msg, i+32, v);
1557 // void(float index, float type, .void field) SV_AddStat = #470;
1558 // Set up an auto-sent player stat.
1559 // Client's get thier own fields sent to them. Index may not be less than 32.
1560 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1561 // 1: string (4 stats carrying a total of 16 charactures)
1562 // 2: float (one stat, float converted to an integer for transportation)
1563 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1564 void PF_SV_AddStat (void)
1569 if(!vm_autosentstats)
1571 vm_autosentstats = (autosentstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(autosentstat_t));
1572 if(!vm_autosentstats)
1574 VM_Warning("PF_SV_AddStat: not enough memory\n");
1578 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1579 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1580 off = PRVM_G_INT (OFS_PARM2);
1585 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1588 if(i >= (MAX_CL_STATS-32))
1590 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1593 if(i > (MAX_CL_STATS-32-4) && type == 1)
1595 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1598 vm_autosentstats[i].type = type;
1599 vm_autosentstats[i].fieldoffset = off;
1600 if(vm_autosentstats_last < i)
1601 vm_autosentstats_last = i;
1608 copies data from one entity to another
1610 copyentity(src, dst)
1613 void PF_copyentity (void)
1615 prvm_edict_t *in, *out;
1616 in = PRVM_G_EDICT(OFS_PARM0);
1617 if (in == prog->edicts)
1619 VM_Warning("copyentity: can not read world entity\n");
1622 if (in->priv.server->free)
1624 VM_Warning("copyentity: can not read free entity\n");
1627 out = PRVM_G_EDICT(OFS_PARM1);
1628 if (out == prog->edicts)
1630 VM_Warning("copyentity: can not modify world entity\n");
1633 if (out->priv.server->free)
1635 VM_Warning("copyentity: can not modify free entity\n");
1638 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1646 sets the color of a client and broadcasts the update to all connected clients
1648 setcolor(clientent, value)
1651 void PF_setcolor (void)
1657 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1658 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1660 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1662 Con_Print("tried to setcolor a non-client\n");
1666 client = svs.clients + entnum-1;
1669 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1671 client->edict->fields.server->team = (i & 15) + 1;
1674 if (client->old_colors != client->colors)
1676 client->old_colors = client->colors;
1677 // send notification to all clients
1678 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1679 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1680 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1688 effect(origin, modelname, startframe, framecount, framerate)
1691 void PF_effect (void)
1695 s = PRVM_G_STRING(OFS_PARM1);
1698 VM_Warning("effect: no model specified\n");
1702 i = SV_ModelIndex(s, 1);
1705 VM_Warning("effect: model not precached\n");
1708 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));
1711 void PF_te_blood (void)
1713 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1715 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1716 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1718 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1719 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1720 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1722 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1723 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1724 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1726 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1729 void PF_te_bloodshower (void)
1731 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1733 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1734 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1736 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1737 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1738 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1740 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1741 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1742 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1744 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1746 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1749 void PF_te_explosionrgb (void)
1751 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1752 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1754 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1755 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1756 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1758 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1759 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1760 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1763 void PF_te_particlecube (void)
1765 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1767 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1768 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1770 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1771 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1772 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1774 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1775 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1776 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1778 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1779 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1780 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1782 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1784 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1785 // gravity true/false
1786 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1788 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1791 void PF_te_particlerain (void)
1793 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1795 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1796 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1798 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1799 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1800 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1802 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1803 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1804 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1808 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1810 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1812 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1815 void PF_te_particlesnow (void)
1817 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1819 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1820 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1822 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1823 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1824 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1826 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1827 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1828 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1830 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1831 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1832 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1834 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1836 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1839 void PF_te_spark (void)
1841 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1843 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1844 MSG_WriteByte(&sv.datagram, TE_SPARK);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1847 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1848 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1850 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1851 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1852 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1854 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1857 void PF_te_gunshotquad (void)
1859 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1860 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1862 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1863 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1864 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1867 void PF_te_spikequad (void)
1869 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1870 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1873 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1874 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1877 void PF_te_superspikequad (void)
1879 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1880 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1882 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1883 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1884 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1887 void PF_te_explosionquad (void)
1889 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1890 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1892 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1893 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1894 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1897 void PF_te_smallflash (void)
1899 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1900 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1907 void PF_te_customflash (void)
1909 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1911 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1912 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1914 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1915 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1916 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1918 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1920 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1922 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1923 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1924 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1927 void PF_te_gunshot (void)
1929 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1930 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1934 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1937 void PF_te_spike (void)
1939 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1940 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1942 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1943 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1944 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1947 void PF_te_superspike (void)
1949 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1950 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1952 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1953 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1954 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1957 void PF_te_explosion (void)
1959 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1960 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1964 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1967 void PF_te_tarexplosion (void)
1969 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1970 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1972 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1973 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1974 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1977 void PF_te_wizspike (void)
1979 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1980 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1983 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1984 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1987 void PF_te_knightspike (void)
1989 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1990 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1992 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1993 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1994 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1997 void PF_te_lavasplash (void)
1999 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2000 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2002 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2004 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2007 void PF_te_teleport (void)
2009 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2010 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2012 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2014 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2017 void PF_te_explosion2 (void)
2019 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2020 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2022 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2023 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2024 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2026 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2027 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2030 void PF_te_lightning1 (void)
2032 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2033 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2035 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2037 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2038 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2039 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2041 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2042 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2043 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2046 void PF_te_lightning2 (void)
2048 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2049 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2051 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2054 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2055 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2058 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2059 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2062 void PF_te_lightning3 (void)
2064 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2065 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2067 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2069 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2070 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2071 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2074 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2075 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2078 void PF_te_beam (void)
2080 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2081 MSG_WriteByte(&sv.datagram, TE_BEAM);
2083 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2085 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2086 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2087 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2089 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2090 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2091 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2094 void PF_te_plasmaburn (void)
2096 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2097 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2098 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2099 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2100 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2103 void PF_te_flamejet (void)
2105 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2106 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2108 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2109 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2110 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2112 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2113 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2114 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2116 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2119 void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2122 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2124 bestdist = 1000000000;
2126 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2128 // clip original point to each triangle of the surface and find the
2129 // triangle that is closest
2130 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2131 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2132 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2133 TriangleNormal(v[0], v[1], v[2], facenormal);
2134 VectorNormalize(facenormal);
2135 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2136 VectorMA(p, offsetdist, facenormal, temp);
2137 for (j = 0, k = 2;j < 3;k = j, j++)
2139 VectorSubtract(v[k], v[j], edgenormal);
2140 CrossProduct(edgenormal, facenormal, sidenormal);
2141 VectorNormalize(sidenormal);
2142 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2144 VectorMA(temp, offsetdist, sidenormal, temp);
2146 dist = VectorDistance2(temp, p);
2147 if (bestdist > dist)
2150 VectorCopy(temp, out);
2155 static model_t *getmodel(prvm_edict_t *ed)
2158 if (!ed || ed->priv.server->free)
2160 modelindex = (int)ed->fields.server->modelindex;
2161 if (modelindex < 1 || modelindex >= MAX_MODELS)
2163 return sv.models[modelindex];
2166 static msurface_t *getsurface(model_t *model, int surfacenum)
2168 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2170 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2174 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2175 void PF_getsurfacenumpoints(void)
2178 msurface_t *surface;
2179 // return 0 if no such surface
2180 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2182 PRVM_G_FLOAT(OFS_RETURN) = 0;
2186 // note: this (incorrectly) assumes it is a simple polygon
2187 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2189 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2190 void PF_getsurfacepoint(void)
2194 msurface_t *surface;
2196 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2197 ed = PRVM_G_EDICT(OFS_PARM0);
2198 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2200 // note: this (incorrectly) assumes it is a simple polygon
2201 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2202 if (pointnum < 0 || pointnum >= surface->num_vertices)
2204 // FIXME: implement rotation/scaling
2205 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2207 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2208 void PF_getsurfacenormal(void)
2211 msurface_t *surface;
2213 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2214 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2216 // FIXME: implement rotation/scaling
2217 // note: this (incorrectly) assumes it is a simple polygon
2218 // note: this only returns the first triangle, so it doesn't work very
2219 // well for curved surfaces or arbitrary meshes
2220 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);
2221 VectorNormalize(normal);
2222 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2224 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2225 void PF_getsurfacetexture(void)
2228 msurface_t *surface;
2229 PRVM_G_INT(OFS_RETURN) = 0;
2230 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2232 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
2234 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2235 void PF_getsurfacenearpoint(void)
2237 int surfacenum, best;
2239 vec_t dist, bestdist;
2242 msurface_t *surface;
2244 PRVM_G_FLOAT(OFS_RETURN) = -1;
2245 ed = PRVM_G_EDICT(OFS_PARM0);
2246 point = PRVM_G_VECTOR(OFS_PARM1);
2248 if (!ed || ed->priv.server->free)
2250 model = getmodel(ed);
2251 if (!model || !model->num_surfaces)
2254 // FIXME: implement rotation/scaling
2255 VectorSubtract(point, ed->fields.server->origin, p);
2257 bestdist = 1000000000;
2258 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2260 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2261 // first see if the nearest point on the surface's box is closer than the previous match
2262 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2263 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2264 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2265 dist = VectorLength2(clipped);
2266 if (dist < bestdist)
2268 // it is, check the nearest point on the actual geometry
2269 clippointtosurface(model, surface, p, clipped);
2270 VectorSubtract(clipped, p, clipped);
2271 dist += VectorLength2(clipped);
2272 if (dist < bestdist)
2274 // that's closer too, store it as the best match
2280 PRVM_G_FLOAT(OFS_RETURN) = best;
2282 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2283 void PF_getsurfaceclippedpoint(void)
2287 msurface_t *surface;
2289 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2290 ed = PRVM_G_EDICT(OFS_PARM0);
2291 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2293 // FIXME: implement rotation/scaling
2294 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2295 clippointtosurface(model, surface, p, out);
2296 // FIXME: implement rotation/scaling
2297 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2300 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2301 //this function originally written by KrimZon, made shorter by LordHavoc
2302 void PF_clientcommand (void)
2304 client_t *temp_client;
2307 //find client for this entity
2308 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2309 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2311 Con_Print("PF_clientcommand: entity is not a client\n");
2315 temp_client = host_client;
2316 host_client = svs.clients + i;
2317 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2318 host_client = temp_client;
2321 //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)
2322 void PF_setattachment (void)
2324 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2325 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2326 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2331 if (e == prog->edicts)
2333 VM_Warning("setattachment: can not modify world entity\n");
2336 if (e->priv.server->free)
2338 VM_Warning("setattachment: can not modify free entity\n");
2342 if (tagentity == NULL)
2343 tagentity = prog->edicts;
2345 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2347 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2349 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2352 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2354 modelindex = (int)tagentity->fields.server->modelindex;
2355 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2357 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2359 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);
2362 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));
2366 /////////////////////////////////////////
2367 // DP_MD3_TAGINFO extension coded by VorteX
2369 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2374 i = (int)e->fields.server->modelindex;
2375 if (i < 1 || i >= MAX_MODELS)
2377 model = sv.models[i];
2379 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2382 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2384 float scale = PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float;
2388 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);
2390 Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2], -ent->fields.server->angles[0], ent->fields.server->angles[1], ent->fields.server->angles[2], scale * cl_viewmodel_scale.value);
2393 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2399 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2400 && (model = sv.models[(int)ent->fields.server->modelindex])
2401 && model->animscenes)
2403 // if model has wrong frame, engine automatically switches to model first frame
2404 frame = (int)ent->fields.server->frame;
2405 if (frame < 0 || frame >= model->numframes)
2407 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2409 *out = identitymatrix;
2413 // Warnings/errors code:
2414 // 0 - normal (everything all-right)
2417 // 3 - null or non-precached model
2418 // 4 - no tags with requested index
2419 // 5 - runaway loop at attachment chain
2420 extern cvar_t cl_bob;
2421 extern cvar_t cl_bobcycle;
2422 extern cvar_t cl_bobup;
2423 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2427 int modelindex, attachloop;
2428 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2431 *out = identitymatrix; // warnings and errors return identical matrix
2433 if (ent == prog->edicts)
2435 if (ent->priv.server->free)
2438 modelindex = (int)ent->fields.server->modelindex;
2439 if (modelindex <= 0 || modelindex > MAX_MODELS)
2442 model = sv.models[modelindex];
2444 tagmatrix = identitymatrix;
2445 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2449 if (attachloop >= 256) // prevent runaway looping
2451 // apply transformation by child's tagindex on parent entity and then
2452 // by parent entity itself
2453 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2454 if (ret && attachloop == 0)
2456 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2457 SV_GetEntityMatrix(ent, &entitymatrix, false);
2458 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2459 // next iteration we process the parent entity
2460 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2462 tagindex = (int)PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
2463 ent = PRVM_EDICT_NUM(val->edict);
2470 // RENDER_VIEWMODEL magic
2471 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2473 Matrix4x4_Copy(&tagmatrix, out);
2474 ent = PRVM_EDICT_NUM(val->edict);
2476 SV_GetEntityMatrix(ent, &entitymatrix, true);
2477 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2480 // Cl_bob, ported from rendering code
2481 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2484 // LordHavoc: this code is *weird*, but not replacable (I think it
2485 // should be done in QC on the server, but oh well, quake is quake)
2486 // LordHavoc: figured out bobup: the time at which the sin is at 180
2487 // degrees (which allows lengthening or squishing the peak or valley)
2488 cycle = sv.time/cl_bobcycle.value;
2489 cycle -= (int)cycle;
2490 if (cycle < cl_bobup.value)
2491 cycle = sin(M_PI * cycle / cl_bobup.value);
2493 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2494 // bob is proportional to velocity in the xy plane
2495 // (don't count Z, or jumping messes it up)
2496 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;
2497 bob = bob*0.3 + bob*0.7*cycle;
2498 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2505 //float(entity ent, string tagname) gettagindex;
2507 void PF_gettagindex (void)
2509 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2510 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2511 int modelindex, tag_index;
2513 if (ent == prog->edicts)
2515 VM_Warning("gettagindex: can't affect world entity\n");
2518 if (ent->priv.server->free)
2520 VM_Warning("gettagindex: can't affect free entity\n");
2524 modelindex = (int)ent->fields.server->modelindex;
2526 if (modelindex <= 0 || modelindex > MAX_MODELS)
2527 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2530 tag_index = SV_GetTagIndex(ent, tag_name);
2532 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2534 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2537 //vector(entity ent, float tagindex) gettaginfo;
2538 void PF_gettaginfo (void)
2540 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2541 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2542 matrix4x4_t tag_matrix;
2545 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2546 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2551 VM_Warning("gettagindex: can't affect world entity\n");
2554 VM_Warning("gettagindex: can't affect free entity\n");
2557 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2560 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2563 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2568 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2569 void PF_dropclient (void)
2572 client_t *oldhostclient;
2573 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2574 if (clientnum < 0 || clientnum >= svs.maxclients)
2576 VM_Warning("dropclient: not a client\n");
2579 if (!svs.clients[clientnum].active)
2581 VM_Warning("dropclient: that client slot is not connected\n");
2584 oldhostclient = host_client;
2585 host_client = svs.clients + clientnum;
2586 SV_DropClient(false);
2587 host_client = oldhostclient;
2590 //entity() spawnclient (DP_SV_BOTCLIENT)
2591 void PF_spawnclient (void)
2595 prog->xfunction->builtinsprofile += 2;
2597 for (i = 0;i < svs.maxclients;i++)
2599 if (!svs.clients[i].active)
2601 prog->xfunction->builtinsprofile += 100;
2602 SV_ConnectClient (i, NULL);
2603 // this has to be set or else ClientDisconnect won't be called
2604 // we assume the qc will call ClientConnect...
2605 svs.clients[i].clientconnectcalled = true;
2606 ed = PRVM_EDICT_NUM(i + 1);
2610 VM_RETURN_EDICT(ed);
2613 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2614 void PF_clienttype (void)
2617 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2618 if (clientnum < 0 || clientnum >= svs.maxclients)
2619 PRVM_G_FLOAT(OFS_RETURN) = 3;
2620 else if (!svs.clients[clientnum].active)
2621 PRVM_G_FLOAT(OFS_RETURN) = 0;
2622 else if (svs.clients[clientnum].netconnection)
2623 PRVM_G_FLOAT(OFS_RETURN) = 1;
2625 PRVM_G_FLOAT(OFS_RETURN) = 2;
2628 void PF_edict_num (void)
2630 VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0)));
2633 prvm_builtin_t vm_sv_builtins[] = {
2635 PF_makevectors, // #1 void(vector ang) makevectors
2636 PF_setorigin, // #2 void(entity e, vector o) setorigin
2637 PF_setmodel, // #3 void(entity e, string m) setmodel
2638 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2639 NULL, // #5 void(entity e, vector min, vector max) setabssize
2640 VM_break, // #6 void() break
2641 VM_random, // #7 float() random
2642 PF_sound, // #8 void(entity e, float chan, string samp) sound
2643 VM_normalize, // #9 vector(vector v) normalize
2644 VM_error, // #10 void(string e) error
2645 VM_objerror, // #11 void(string e) objerror
2646 VM_vlen, // #12 float(vector v) vlen
2647 VM_vectoyaw, // #13 float(vector v) vectoyaw
2648 VM_spawn, // #14 entity() spawn
2649 VM_remove, // #15 void(entity e) remove
2650 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2651 PF_checkclient, // #17 entity() clientlist
2652 VM_find, // #18 entity(entity start, .string fld, string match) find
2653 PF_precache_sound, // #19 void(string s) precache_sound
2654 PF_precache_model, // #20 void(string s) precache_model
2655 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2656 PF_findradius, // #22 entity(vector org, float rad) findradius
2657 VM_bprint, // #23 void(string s) bprint
2658 PF_sprint, // #24 void(entity client, string s) sprint
2659 VM_dprint, // #25 void(string s) dprint
2660 VM_ftos, // #26 void(string s) ftos
2661 VM_vtos, // #27 void(string s) vtos
2662 VM_coredump, // #28 void() coredump
2663 VM_traceon, // #29 void() traceon
2664 VM_traceoff, // #30 void() traceoff
2665 VM_eprint, // #31 void(entity e) eprint
2666 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2668 PF_droptofloor, // #34 float() droptofloor
2669 PF_lightstyle, // #35 void(float style, string value) lightstyle
2670 VM_rint, // #36 float(float v) rint
2671 VM_floor, // #37 float(float v) floor
2672 VM_ceil, // #38 float(float v) ceil
2674 PF_checkbottom, // #40 float(entity e) checkbottom
2675 PF_pointcontents, // #41 float(vector v) pointcontents
2677 VM_fabs, // #43 float(float f) fabs
2678 PF_aim, // #44 vector(entity e, float speed) aim
2679 VM_cvar, // #45 float(string s) cvar
2680 VM_localcmd, // #46 void(string s) localcmd
2681 VM_nextent, // #47 entity(entity e) nextent
2682 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2683 PF_changeyaw, // #49 void() ChangeYaw
2685 VM_vectoangles, // #51 vector(vector v) vectoangles
2686 PF_WriteByte, // #52 void(float to, float f) WriteByte
2687 PF_WriteChar, // #53 void(float to, float f) WriteChar
2688 PF_WriteShort, // #54 void(float to, float f) WriteShort
2689 PF_WriteLong, // #55 void(float to, float f) WriteLong
2690 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2691 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2692 PF_WriteString, // #58 void(float to, string s) WriteString
2693 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2694 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2695 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2696 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2697 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2698 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2699 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2701 SV_MoveToGoal, // #67 void(float step) movetogoal
2702 PF_precache_file, // #68 string(string s) precache_file
2703 PF_makestatic, // #69 void(entity e) makestatic
2704 VM_changelevel, // #70 void(string s) changelevel
2706 VM_cvar_set, // #72 void(string var, string val) cvar_set
2707 PF_centerprint, // #73 void(entity client, strings) centerprint
2708 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2709 PF_precache_model, // #75 string(string s) precache_model2
2710 PF_precache_sound, // #76 string(string s) precache_sound2
2711 PF_precache_file, // #77 string(string s) precache_file2
2712 PF_setspawnparms, // #78 void(entity e) setspawnparms
2715 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2724 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2725 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2726 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2727 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2728 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2729 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2730 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2731 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2732 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2733 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2744 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2745 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2746 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2747 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2748 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2749 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2750 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2751 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2752 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2753 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2754 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2755 // FTEQW range #200-#299
2774 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2784 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2785 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2786 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2787 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2788 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2789 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2790 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2791 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2792 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2793 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2794 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2795 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2796 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2797 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2798 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2799 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2800 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2801 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2802 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2803 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2804 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2805 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2806 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2807 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2808 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2809 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2810 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2811 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2812 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2813 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2814 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2815 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2816 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2817 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2818 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2819 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2820 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2821 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2822 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2823 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2824 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2825 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2826 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2827 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2828 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2829 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2830 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2831 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2832 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2833 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2834 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2835 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2836 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2837 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2838 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2839 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2840 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2841 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2842 PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2844 PF_edict_num, // #459 entity(float num) (??)
2845 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2846 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2847 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2848 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2849 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2850 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2851 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2852 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2853 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2854 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2855 PF_SV_AddStat, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2856 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
2857 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
2858 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
2859 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
2860 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
2861 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
2862 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
2865 e10, e10 // #480-499 (LordHavoc)
2868 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2870 void VM_SV_Cmd_Init(void)
2875 void VM_SV_Cmd_Reset(void)