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");
1709 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1711 VM_Warning("effect: framecount < 1\n");
1715 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1717 VM_Warning("effect: framerate < 1\n");
1721 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));
1724 void PF_te_blood (void)
1726 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1728 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1729 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1731 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1732 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1733 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1735 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1736 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1737 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1739 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1742 void PF_te_bloodshower (void)
1744 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1746 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1747 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1749 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1750 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1751 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1753 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1754 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1755 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1757 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1759 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1762 void PF_te_explosionrgb (void)
1764 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1765 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1767 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1768 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1769 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1771 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1772 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1773 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1776 void PF_te_particlecube (void)
1778 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1780 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1781 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1783 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1784 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1785 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1787 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1788 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1789 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1791 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1792 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1793 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1795 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1797 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1798 // gravity true/false
1799 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1801 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1804 void PF_te_particlerain (void)
1806 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1808 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1809 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1812 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1813 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1815 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1816 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1817 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1819 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1820 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1821 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1823 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1825 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1828 void PF_te_particlesnow (void)
1830 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1832 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1833 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1835 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1836 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1837 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1839 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1840 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1841 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1843 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1844 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1845 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1847 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1849 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1852 void PF_te_spark (void)
1854 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1856 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1857 MSG_WriteByte(&sv.datagram, TE_SPARK);
1859 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1860 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1861 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1863 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1864 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1865 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1867 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1870 void PF_te_gunshotquad (void)
1872 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1873 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
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_spikequad (void)
1882 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1883 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
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_superspikequad (void)
1892 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1893 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
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_explosionquad (void)
1902 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1903 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
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_smallflash (void)
1912 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1913 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
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_customflash (void)
1922 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1924 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1925 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1931 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1933 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1935 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1936 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1937 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1940 void PF_te_gunshot (void)
1942 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1943 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1945 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1950 void PF_te_spike (void)
1952 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1953 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1955 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1960 void PF_te_superspike (void)
1962 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1963 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1965 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1970 void PF_te_explosion (void)
1972 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1973 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1975 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1976 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1977 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1980 void PF_te_tarexplosion (void)
1982 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1983 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1985 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1990 void PF_te_wizspike (void)
1992 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1993 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1995 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1996 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1997 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2000 void PF_te_knightspike (void)
2002 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2003 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2005 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2006 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2007 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2010 void PF_te_lavasplash (void)
2012 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2013 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2015 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2016 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2017 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2020 void PF_te_teleport (void)
2022 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2023 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2025 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2026 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2030 void PF_te_explosion2 (void)
2032 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2033 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2035 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2036 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2037 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2039 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2040 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2043 void PF_te_lightning1 (void)
2045 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2046 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2048 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2050 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2052 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2054 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2055 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2056 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2059 void PF_te_lightning2 (void)
2061 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2062 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2064 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2066 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2067 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2068 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2070 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2071 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2072 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2075 void PF_te_lightning3 (void)
2077 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2078 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2080 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2082 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2083 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2084 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2086 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2087 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2088 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2091 void PF_te_beam (void)
2093 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2094 MSG_WriteByte(&sv.datagram, TE_BEAM);
2096 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2098 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2099 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2100 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2102 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2103 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2104 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2107 void PF_te_plasmaburn (void)
2109 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2110 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2111 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2112 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2113 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2116 void PF_te_flamejet (void)
2118 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2119 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2121 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2122 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2123 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2125 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2126 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2127 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2129 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2132 void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2135 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2137 bestdist = 1000000000;
2139 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2141 // clip original point to each triangle of the surface and find the
2142 // triangle that is closest
2143 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2144 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2145 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2146 TriangleNormal(v[0], v[1], v[2], facenormal);
2147 VectorNormalize(facenormal);
2148 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2149 VectorMA(p, offsetdist, facenormal, temp);
2150 for (j = 0, k = 2;j < 3;k = j, j++)
2152 VectorSubtract(v[k], v[j], edgenormal);
2153 CrossProduct(edgenormal, facenormal, sidenormal);
2154 VectorNormalize(sidenormal);
2155 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2157 VectorMA(temp, offsetdist, sidenormal, temp);
2159 dist = VectorDistance2(temp, p);
2160 if (bestdist > dist)
2163 VectorCopy(temp, out);
2168 static model_t *getmodel(prvm_edict_t *ed)
2171 if (!ed || ed->priv.server->free)
2173 modelindex = (int)ed->fields.server->modelindex;
2174 if (modelindex < 1 || modelindex >= MAX_MODELS)
2176 return sv.models[modelindex];
2179 static msurface_t *getsurface(model_t *model, int surfacenum)
2181 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2183 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2187 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2188 void PF_getsurfacenumpoints(void)
2191 msurface_t *surface;
2192 // return 0 if no such surface
2193 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2195 PRVM_G_FLOAT(OFS_RETURN) = 0;
2199 // note: this (incorrectly) assumes it is a simple polygon
2200 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2202 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2203 void PF_getsurfacepoint(void)
2207 msurface_t *surface;
2209 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2210 ed = PRVM_G_EDICT(OFS_PARM0);
2211 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2213 // note: this (incorrectly) assumes it is a simple polygon
2214 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2215 if (pointnum < 0 || pointnum >= surface->num_vertices)
2217 // FIXME: implement rotation/scaling
2218 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2220 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2221 void PF_getsurfacenormal(void)
2224 msurface_t *surface;
2226 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2227 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2229 // FIXME: implement rotation/scaling
2230 // note: this (incorrectly) assumes it is a simple polygon
2231 // note: this only returns the first triangle, so it doesn't work very
2232 // well for curved surfaces or arbitrary meshes
2233 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);
2234 VectorNormalize(normal);
2235 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2237 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2238 void PF_getsurfacetexture(void)
2241 msurface_t *surface;
2242 PRVM_G_INT(OFS_RETURN) = 0;
2243 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2245 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
2247 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2248 void PF_getsurfacenearpoint(void)
2250 int surfacenum, best;
2252 vec_t dist, bestdist;
2255 msurface_t *surface;
2257 PRVM_G_FLOAT(OFS_RETURN) = -1;
2258 ed = PRVM_G_EDICT(OFS_PARM0);
2259 point = PRVM_G_VECTOR(OFS_PARM1);
2261 if (!ed || ed->priv.server->free)
2263 model = getmodel(ed);
2264 if (!model || !model->num_surfaces)
2267 // FIXME: implement rotation/scaling
2268 VectorSubtract(point, ed->fields.server->origin, p);
2270 bestdist = 1000000000;
2271 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2273 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2274 // first see if the nearest point on the surface's box is closer than the previous match
2275 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2276 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2277 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2278 dist = VectorLength2(clipped);
2279 if (dist < bestdist)
2281 // it is, check the nearest point on the actual geometry
2282 clippointtosurface(model, surface, p, clipped);
2283 VectorSubtract(clipped, p, clipped);
2284 dist += VectorLength2(clipped);
2285 if (dist < bestdist)
2287 // that's closer too, store it as the best match
2293 PRVM_G_FLOAT(OFS_RETURN) = best;
2295 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2296 void PF_getsurfaceclippedpoint(void)
2300 msurface_t *surface;
2302 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2303 ed = PRVM_G_EDICT(OFS_PARM0);
2304 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2306 // FIXME: implement rotation/scaling
2307 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2308 clippointtosurface(model, surface, p, out);
2309 // FIXME: implement rotation/scaling
2310 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2313 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2314 //this function originally written by KrimZon, made shorter by LordHavoc
2315 void PF_clientcommand (void)
2317 client_t *temp_client;
2320 //find client for this entity
2321 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2322 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2324 Con_Print("PF_clientcommand: entity is not a client\n");
2328 temp_client = host_client;
2329 host_client = svs.clients + i;
2330 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2331 host_client = temp_client;
2334 //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)
2335 void PF_setattachment (void)
2337 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2338 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2339 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2344 if (e == prog->edicts)
2346 VM_Warning("setattachment: can not modify world entity\n");
2349 if (e->priv.server->free)
2351 VM_Warning("setattachment: can not modify free entity\n");
2355 if (tagentity == NULL)
2356 tagentity = prog->edicts;
2358 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2360 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2362 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2365 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2367 modelindex = (int)tagentity->fields.server->modelindex;
2368 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2370 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2372 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);
2375 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));
2379 /////////////////////////////////////////
2380 // DP_MD3_TAGINFO extension coded by VorteX
2382 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2387 i = (int)e->fields.server->modelindex;
2388 if (i < 1 || i >= MAX_MODELS)
2390 model = sv.models[i];
2392 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2395 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2397 float scale = PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float;
2401 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);
2403 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);
2406 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2412 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2413 && (model = sv.models[(int)ent->fields.server->modelindex])
2414 && model->animscenes)
2416 // if model has wrong frame, engine automatically switches to model first frame
2417 frame = (int)ent->fields.server->frame;
2418 if (frame < 0 || frame >= model->numframes)
2420 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2422 *out = identitymatrix;
2426 // Warnings/errors code:
2427 // 0 - normal (everything all-right)
2430 // 3 - null or non-precached model
2431 // 4 - no tags with requested index
2432 // 5 - runaway loop at attachment chain
2433 extern cvar_t cl_bob;
2434 extern cvar_t cl_bobcycle;
2435 extern cvar_t cl_bobup;
2436 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2440 int modelindex, attachloop;
2441 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2444 *out = identitymatrix; // warnings and errors return identical matrix
2446 if (ent == prog->edicts)
2448 if (ent->priv.server->free)
2451 modelindex = (int)ent->fields.server->modelindex;
2452 if (modelindex <= 0 || modelindex > MAX_MODELS)
2455 model = sv.models[modelindex];
2457 tagmatrix = identitymatrix;
2458 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2462 if (attachloop >= 256) // prevent runaway looping
2464 // apply transformation by child's tagindex on parent entity and then
2465 // by parent entity itself
2466 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2467 if (ret && attachloop == 0)
2469 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2470 SV_GetEntityMatrix(ent, &entitymatrix, false);
2471 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2472 // next iteration we process the parent entity
2473 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2475 tagindex = (int)PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
2476 ent = PRVM_EDICT_NUM(val->edict);
2483 // RENDER_VIEWMODEL magic
2484 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2486 Matrix4x4_Copy(&tagmatrix, out);
2487 ent = PRVM_EDICT_NUM(val->edict);
2489 SV_GetEntityMatrix(ent, &entitymatrix, true);
2490 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2493 // Cl_bob, ported from rendering code
2494 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2497 // LordHavoc: this code is *weird*, but not replacable (I think it
2498 // should be done in QC on the server, but oh well, quake is quake)
2499 // LordHavoc: figured out bobup: the time at which the sin is at 180
2500 // degrees (which allows lengthening or squishing the peak or valley)
2501 cycle = sv.time/cl_bobcycle.value;
2502 cycle -= (int)cycle;
2503 if (cycle < cl_bobup.value)
2504 cycle = sin(M_PI * cycle / cl_bobup.value);
2506 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2507 // bob is proportional to velocity in the xy plane
2508 // (don't count Z, or jumping messes it up)
2509 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;
2510 bob = bob*0.3 + bob*0.7*cycle;
2511 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2518 //float(entity ent, string tagname) gettagindex;
2520 void PF_gettagindex (void)
2522 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2523 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2524 int modelindex, tag_index;
2526 if (ent == prog->edicts)
2528 VM_Warning("gettagindex: can't affect world entity\n");
2531 if (ent->priv.server->free)
2533 VM_Warning("gettagindex: can't affect free entity\n");
2537 modelindex = (int)ent->fields.server->modelindex;
2539 if (modelindex <= 0 || modelindex > MAX_MODELS)
2540 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2543 tag_index = SV_GetTagIndex(ent, tag_name);
2545 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2547 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2550 //vector(entity ent, float tagindex) gettaginfo;
2551 void PF_gettaginfo (void)
2553 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2554 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2555 matrix4x4_t tag_matrix;
2558 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2559 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2564 VM_Warning("gettagindex: can't affect world entity\n");
2567 VM_Warning("gettagindex: can't affect free entity\n");
2570 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2573 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2576 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2581 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2582 void PF_dropclient (void)
2585 client_t *oldhostclient;
2586 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2587 if (clientnum < 0 || clientnum >= svs.maxclients)
2589 VM_Warning("dropclient: not a client\n");
2592 if (!svs.clients[clientnum].active)
2594 VM_Warning("dropclient: that client slot is not connected\n");
2597 oldhostclient = host_client;
2598 host_client = svs.clients + clientnum;
2599 SV_DropClient(false);
2600 host_client = oldhostclient;
2603 //entity() spawnclient (DP_SV_BOTCLIENT)
2604 void PF_spawnclient (void)
2608 prog->xfunction->builtinsprofile += 2;
2610 for (i = 0;i < svs.maxclients;i++)
2612 if (!svs.clients[i].active)
2614 prog->xfunction->builtinsprofile += 100;
2615 SV_ConnectClient (i, NULL);
2616 // this has to be set or else ClientDisconnect won't be called
2617 // we assume the qc will call ClientConnect...
2618 svs.clients[i].clientconnectcalled = true;
2619 ed = PRVM_EDICT_NUM(i + 1);
2623 VM_RETURN_EDICT(ed);
2626 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2627 void PF_clienttype (void)
2630 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2631 if (clientnum < 0 || clientnum >= svs.maxclients)
2632 PRVM_G_FLOAT(OFS_RETURN) = 3;
2633 else if (!svs.clients[clientnum].active)
2634 PRVM_G_FLOAT(OFS_RETURN) = 0;
2635 else if (svs.clients[clientnum].netconnection)
2636 PRVM_G_FLOAT(OFS_RETURN) = 1;
2638 PRVM_G_FLOAT(OFS_RETURN) = 2;
2641 void PF_edict_num (void)
2643 VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0)));
2646 prvm_builtin_t vm_sv_builtins[] = {
2648 PF_makevectors, // #1 void(vector ang) makevectors
2649 PF_setorigin, // #2 void(entity e, vector o) setorigin
2650 PF_setmodel, // #3 void(entity e, string m) setmodel
2651 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2652 NULL, // #5 void(entity e, vector min, vector max) setabssize
2653 VM_break, // #6 void() break
2654 VM_random, // #7 float() random
2655 PF_sound, // #8 void(entity e, float chan, string samp) sound
2656 VM_normalize, // #9 vector(vector v) normalize
2657 VM_error, // #10 void(string e) error
2658 VM_objerror, // #11 void(string e) objerror
2659 VM_vlen, // #12 float(vector v) vlen
2660 VM_vectoyaw, // #13 float(vector v) vectoyaw
2661 VM_spawn, // #14 entity() spawn
2662 VM_remove, // #15 void(entity e) remove
2663 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2664 PF_checkclient, // #17 entity() clientlist
2665 VM_find, // #18 entity(entity start, .string fld, string match) find
2666 PF_precache_sound, // #19 void(string s) precache_sound
2667 PF_precache_model, // #20 void(string s) precache_model
2668 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2669 PF_findradius, // #22 entity(vector org, float rad) findradius
2670 VM_bprint, // #23 void(string s) bprint
2671 PF_sprint, // #24 void(entity client, string s) sprint
2672 VM_dprint, // #25 void(string s) dprint
2673 VM_ftos, // #26 void(string s) ftos
2674 VM_vtos, // #27 void(string s) vtos
2675 VM_coredump, // #28 void() coredump
2676 VM_traceon, // #29 void() traceon
2677 VM_traceoff, // #30 void() traceoff
2678 VM_eprint, // #31 void(entity e) eprint
2679 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2681 PF_droptofloor, // #34 float() droptofloor
2682 PF_lightstyle, // #35 void(float style, string value) lightstyle
2683 VM_rint, // #36 float(float v) rint
2684 VM_floor, // #37 float(float v) floor
2685 VM_ceil, // #38 float(float v) ceil
2687 PF_checkbottom, // #40 float(entity e) checkbottom
2688 PF_pointcontents, // #41 float(vector v) pointcontents
2690 VM_fabs, // #43 float(float f) fabs
2691 PF_aim, // #44 vector(entity e, float speed) aim
2692 VM_cvar, // #45 float(string s) cvar
2693 VM_localcmd, // #46 void(string s) localcmd
2694 VM_nextent, // #47 entity(entity e) nextent
2695 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2696 PF_changeyaw, // #49 void() ChangeYaw
2698 VM_vectoangles, // #51 vector(vector v) vectoangles
2699 PF_WriteByte, // #52 void(float to, float f) WriteByte
2700 PF_WriteChar, // #53 void(float to, float f) WriteChar
2701 PF_WriteShort, // #54 void(float to, float f) WriteShort
2702 PF_WriteLong, // #55 void(float to, float f) WriteLong
2703 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2704 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2705 PF_WriteString, // #58 void(float to, string s) WriteString
2706 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2707 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2708 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2709 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2710 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2711 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2712 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2714 SV_MoveToGoal, // #67 void(float step) movetogoal
2715 PF_precache_file, // #68 string(string s) precache_file
2716 PF_makestatic, // #69 void(entity e) makestatic
2717 VM_changelevel, // #70 void(string s) changelevel
2719 VM_cvar_set, // #72 void(string var, string val) cvar_set
2720 PF_centerprint, // #73 void(entity client, strings) centerprint
2721 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2722 PF_precache_model, // #75 string(string s) precache_model2
2723 PF_precache_sound, // #76 string(string s) precache_sound2
2724 PF_precache_file, // #77 string(string s) precache_file2
2725 PF_setspawnparms, // #78 void(entity e) setspawnparms
2728 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2737 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2738 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2739 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2740 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2741 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2742 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2743 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2744 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2745 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2746 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2757 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2758 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2759 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2760 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2761 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2762 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2763 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2764 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2765 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2766 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2767 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2768 // FTEQW range #200-#299
2787 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2797 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2798 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2799 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2800 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2801 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2802 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2803 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2804 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2805 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2806 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2807 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2808 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2809 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2810 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2811 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2812 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2813 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2814 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2815 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2816 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2817 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2818 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2819 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2820 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2821 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2822 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2823 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2824 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2825 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2826 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2827 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2828 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2829 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2830 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2831 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2832 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2833 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2834 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2835 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2836 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2837 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2838 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2839 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2840 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2841 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2842 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2843 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2844 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2845 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2846 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2847 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2848 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2849 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2850 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2851 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2852 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2853 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2854 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2855 PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2857 PF_edict_num, // #459 entity(float num) (??)
2858 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2859 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2860 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2861 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2862 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2863 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2864 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2865 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2866 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2867 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2868 PF_SV_AddStat, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2869 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
2870 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
2871 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
2872 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
2873 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
2874 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
2875 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
2878 e10, e10 // #480-499 (LordHavoc)
2881 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2883 void VM_SV_Cmd_Init(void)
2888 void VM_SV_Cmd_Reset(void)