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 || (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer))
943 if (trace.fraction < 1)
944 VectorCopy (trace.endpos, ent->fields.server->origin);
945 SV_LinkEdict (ent, false);
946 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
947 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
948 PRVM_G_FLOAT(OFS_RETURN) = 1;
949 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
950 ent->priv.server->suspendedinairflag = true;
958 void(float style, string value) lightstyle
961 void PF_lightstyle (void)
968 style = (int)PRVM_G_FLOAT(OFS_PARM0);
969 val = PRVM_G_STRING(OFS_PARM1);
971 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
972 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
975 // change the string in sv
976 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
978 // send message to all clients on this server
979 if (sv.state != ss_active)
982 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
984 if (client->active && client->netconnection)
986 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
987 MSG_WriteChar (&client->netconnection->message,style);
988 MSG_WriteString (&client->netconnection->message, val);
998 void PF_checkbottom (void)
1000 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1008 void PF_pointcontents (void)
1010 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1017 Pick a vector for the player to shoot along
1018 vector aim(entity, missilespeed)
1023 prvm_edict_t *ent, *check, *bestent;
1024 vec3_t start, dir, end, bestdir;
1027 float dist, bestdist;
1030 // assume failure if it returns early
1031 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1032 // if sv_aim is so high it can't possibly accept anything, skip out early
1033 if (sv_aim.value >= 1)
1036 ent = PRVM_G_EDICT(OFS_PARM0);
1037 if (ent == prog->edicts)
1039 VM_Warning("aim: can not use world entity\n");
1042 if (ent->priv.server->free)
1044 VM_Warning("aim: can not use free entity\n");
1047 speed = PRVM_G_FLOAT(OFS_PARM1);
1049 VectorCopy (ent->fields.server->origin, start);
1052 // try sending a trace straight
1053 VectorCopy (prog->globals.server->v_forward, dir);
1054 VectorMA (start, 2048, dir, end);
1055 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1056 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1057 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1059 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1064 // try all possible entities
1065 VectorCopy (dir, bestdir);
1066 bestdist = sv_aim.value;
1069 check = PRVM_NEXT_EDICT(prog->edicts);
1070 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1072 prog->xfunction->builtinsprofile++;
1073 if (check->fields.server->takedamage != DAMAGE_AIM)
1077 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1078 continue; // don't aim at teammate
1079 for (j=0 ; j<3 ; j++)
1080 end[j] = check->fields.server->origin[j]
1081 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1082 VectorSubtract (end, start, dir);
1083 VectorNormalize (dir);
1084 dist = DotProduct (dir, prog->globals.server->v_forward);
1085 if (dist < bestdist)
1086 continue; // to far to turn
1087 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1088 if (tr.ent == check)
1089 { // can shoot at this one
1097 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1098 dist = DotProduct (dir, prog->globals.server->v_forward);
1099 VectorScale (prog->globals.server->v_forward, dist, end);
1101 VectorNormalize (end);
1102 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1106 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1114 This was a major timewaster in progs, so it was converted to C
1117 void PF_changeyaw (void)
1120 float ideal, current, move, speed;
1122 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1123 if (ent == prog->edicts)
1125 VM_Warning("changeyaw: can not modify world entity\n");
1128 if (ent->priv.server->free)
1130 VM_Warning("changeyaw: can not modify free entity\n");
1133 current = ANGLEMOD(ent->fields.server->angles[1]);
1134 ideal = ent->fields.server->ideal_yaw;
1135 speed = ent->fields.server->yaw_speed;
1137 if (current == ideal)
1139 move = ideal - current;
1140 if (ideal > current)
1161 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1169 void PF_changepitch (void)
1172 float ideal, current, move, speed;
1175 ent = PRVM_G_EDICT(OFS_PARM0);
1176 if (ent == prog->edicts)
1178 VM_Warning("changepitch: can not modify world entity\n");
1181 if (ent->priv.server->free)
1183 VM_Warning("changepitch: can not modify free entity\n");
1186 current = ANGLEMOD( ent->fields.server->angles[0] );
1187 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1188 ideal = val->_float;
1191 VM_Warning("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1194 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1195 speed = val->_float;
1198 VM_Warning("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1202 if (current == ideal)
1204 move = ideal - current;
1205 if (ideal > current)
1226 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1230 ===============================================================================
1234 ===============================================================================
1237 #define MSG_BROADCAST 0 // unreliable to all
1238 #define MSG_ONE 1 // reliable to one (msg_entity)
1239 #define MSG_ALL 2 // reliable to all
1240 #define MSG_INIT 3 // write to the init string
1241 #define MSG_ENTITY 5
1243 sizebuf_t *WriteDest (void)
1248 extern sizebuf_t *sv2csqcbuf;
1250 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1254 return &sv.datagram;
1257 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1258 entnum = PRVM_NUM_FOR_EDICT(ent);
1259 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1261 VM_Warning ("WriteDest: tried to write to non-client\n");
1262 return &sv.reliable_datagram;
1265 return &svs.clients[entnum-1].netconnection->message;
1268 VM_Warning ("WriteDest: bad destination\n");
1270 return &sv.reliable_datagram;
1282 void PF_WriteByte (void)
1284 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1287 void PF_WriteChar (void)
1289 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1292 void PF_WriteShort (void)
1294 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1297 void PF_WriteLong (void)
1299 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1302 void PF_WriteAngle (void)
1304 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1307 void PF_WriteCoord (void)
1309 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1312 void PF_WriteString (void)
1314 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1317 void PF_WriteUnterminatedString (void)
1319 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1323 void PF_WriteEntity (void)
1325 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1328 //////////////////////////////////////////////////////////
1330 void PF_makestatic (void)
1335 ent = PRVM_G_EDICT(OFS_PARM0);
1336 if (ent == prog->edicts)
1338 VM_Warning("makestatic: can not modify world entity\n");
1341 if (ent->priv.server->free)
1343 VM_Warning("makestatic: can not modify free entity\n");
1348 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1353 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1354 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1355 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1359 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1360 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1361 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1364 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1365 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1366 for (i=0 ; i<3 ; i++)
1368 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1369 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1372 // throw the entity away now
1376 //=============================================================================
1383 void PF_setspawnparms (void)
1389 ent = PRVM_G_EDICT(OFS_PARM0);
1390 i = PRVM_NUM_FOR_EDICT(ent);
1391 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1393 Con_Print("tried to setspawnparms on a non-client\n");
1397 // copy spawn parms out of the client_t
1398 client = svs.clients + i-1;
1399 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1400 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1407 Returns a color vector indicating the lighting at the requested point.
1409 (Internal Operation note: actually measures the light beneath the point, just like
1410 the model lighting on the client)
1415 void PF_getlight (void)
1417 vec3_t ambientcolor, diffusecolor, diffusenormal;
1419 p = PRVM_G_VECTOR(OFS_PARM0);
1420 VectorClear(ambientcolor);
1421 VectorClear(diffusecolor);
1422 VectorClear(diffusenormal);
1423 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1424 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1425 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1428 void PF_registercvar (void)
1430 const char *name, *value;
1431 name = PRVM_G_STRING(OFS_PARM0);
1432 value = PRVM_G_STRING(OFS_PARM1);
1433 PRVM_G_FLOAT(OFS_RETURN) = 0;
1435 // first check to see if it has already been defined
1436 if (Cvar_FindVar (name))
1439 // check for overlap with a command
1440 if (Cmd_Exists (name))
1442 VM_Warning("PF_registercvar: %s is a command\n", name);
1446 Cvar_Get(name, value, 0);
1448 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1453 unsigned char type; // 1/2/8 or other value if isn't used
1457 static autosentstat_t *vm_autosentstats = NULL; //[515]: it starts from 0, not 32
1458 static int vm_autosentstats_last;
1460 void VM_AutoSentStats_Clear (void)
1462 if(vm_autosentstats)
1464 Z_Free(vm_autosentstats);
1465 vm_autosentstats = NULL;
1466 vm_autosentstats_last = -1;
1470 //[515]: add check if even bigger ? "try to use two stats, cause it's too big" ?
1471 #define VM_SENDSTAT(a,b,c)\
1474 if((c)==(unsigned char)(c))\
1476 MSG_WriteByte((a), svc_updatestatubyte);\
1477 MSG_WriteByte((a), (b));\
1478 MSG_WriteByte((a), (c));\
1482 MSG_WriteByte((a), svc_updatestat);\
1483 MSG_WriteByte((a), (b));\
1484 MSG_WriteLong((a), (c));\
1488 void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1500 if(!vm_autosentstats)
1503 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);
1505 for(i=0; i<vm_autosentstats_last+1 ;i++)
1507 if(!vm_autosentstats[i].type)
1509 switch(vm_autosentstats[i].type)
1513 t = PRVM_E_STRING(ent, vm_autosentstats[i].fieldoffset);
1521 stats[i+32] = si[0];
1522 stats[i+33] = si[1];
1523 stats[i+34] = si[2];
1524 stats[i+35] = si[3];
1528 VM_SENDSTAT(msg, i+32, si[0]);
1529 VM_SENDSTAT(msg, i+33, si[1]);
1530 VM_SENDSTAT(msg, i+34, si[2]);
1531 VM_SENDSTAT(msg, i+35, si[3]);
1537 k.f = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1538 k.i = LittleLong (k.i);
1542 VM_SENDSTAT(msg, i+32, k.i);
1546 v = (int)PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1550 VM_SENDSTAT(msg, i+32, v);
1558 // void(float index, float type, .void field) SV_AddStat = #470;
1559 // Set up an auto-sent player stat.
1560 // Client's get thier own fields sent to them. Index may not be less than 32.
1561 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1562 // 1: string (4 stats carrying a total of 16 charactures)
1563 // 2: float (one stat, float converted to an integer for transportation)
1564 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1565 void PF_SV_AddStat (void)
1570 if(!vm_autosentstats)
1572 vm_autosentstats = (autosentstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(autosentstat_t));
1573 if(!vm_autosentstats)
1575 VM_Warning("PF_SV_AddStat: not enough memory\n");
1579 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1580 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1581 off = PRVM_G_INT (OFS_PARM2);
1586 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1589 if(i >= (MAX_CL_STATS-32))
1591 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1594 if(i > (MAX_CL_STATS-32-4) && type == 1)
1596 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1599 vm_autosentstats[i].type = type;
1600 vm_autosentstats[i].fieldoffset = off;
1601 if(vm_autosentstats_last < i)
1602 vm_autosentstats_last = i;
1609 copies data from one entity to another
1611 copyentity(src, dst)
1614 void PF_copyentity (void)
1616 prvm_edict_t *in, *out;
1617 in = PRVM_G_EDICT(OFS_PARM0);
1618 if (in == prog->edicts)
1620 VM_Warning("copyentity: can not read world entity\n");
1623 if (in->priv.server->free)
1625 VM_Warning("copyentity: can not read free entity\n");
1628 out = PRVM_G_EDICT(OFS_PARM1);
1629 if (out == prog->edicts)
1631 VM_Warning("copyentity: can not modify world entity\n");
1634 if (out->priv.server->free)
1636 VM_Warning("copyentity: can not modify free entity\n");
1639 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1647 sets the color of a client and broadcasts the update to all connected clients
1649 setcolor(clientent, value)
1652 void PF_setcolor (void)
1658 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1659 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1661 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1663 Con_Print("tried to setcolor a non-client\n");
1667 client = svs.clients + entnum-1;
1670 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1672 client->edict->fields.server->team = (i & 15) + 1;
1675 if (client->old_colors != client->colors)
1677 client->old_colors = client->colors;
1678 // send notification to all clients
1679 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1680 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1681 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1689 effect(origin, modelname, startframe, framecount, framerate)
1692 void PF_effect (void)
1696 s = PRVM_G_STRING(OFS_PARM1);
1699 VM_Warning("effect: no model specified\n");
1703 i = SV_ModelIndex(s, 1);
1706 VM_Warning("effect: model not precached\n");
1710 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1712 VM_Warning("effect: framecount < 1\n");
1716 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1718 VM_Warning("effect: framerate < 1\n");
1722 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));
1725 void PF_te_blood (void)
1727 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1729 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1730 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1732 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1733 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1734 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1736 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1737 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1738 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1740 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1743 void PF_te_bloodshower (void)
1745 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1747 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1748 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1750 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1751 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1752 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1754 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1755 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1756 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1758 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1760 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1763 void PF_te_explosionrgb (void)
1765 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1766 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1768 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1769 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1770 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1772 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1773 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1774 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1777 void PF_te_particlecube (void)
1779 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1781 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1782 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1784 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1785 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1786 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1788 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1789 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1790 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1792 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1793 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1794 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1796 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1798 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1799 // gravity true/false
1800 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1802 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1805 void PF_te_particlerain (void)
1807 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1809 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1810 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1812 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1813 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1814 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1816 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1817 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1818 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1820 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1821 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1822 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1824 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1826 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1829 void PF_te_particlesnow (void)
1831 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1833 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1834 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1836 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1837 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1838 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1840 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1841 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1842 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1844 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1845 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1848 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1850 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1853 void PF_te_spark (void)
1855 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1857 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1858 MSG_WriteByte(&sv.datagram, TE_SPARK);
1860 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1861 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1862 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1864 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1865 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1866 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1868 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1871 void PF_te_gunshotquad (void)
1873 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1874 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1876 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1877 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1878 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1881 void PF_te_spikequad (void)
1883 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1884 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1886 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1887 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1888 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1891 void PF_te_superspikequad (void)
1893 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1894 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1896 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1901 void PF_te_explosionquad (void)
1903 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1904 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1911 void PF_te_smallflash (void)
1913 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1914 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1916 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1917 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1918 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1921 void PF_te_customflash (void)
1923 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1925 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1926 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1932 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1934 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1936 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1937 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1938 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1941 void PF_te_gunshot (void)
1943 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1944 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1948 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1951 void PF_te_spike (void)
1953 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1954 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1961 void PF_te_superspike (void)
1963 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1964 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1971 void PF_te_explosion (void)
1973 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1974 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1976 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1977 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1978 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1981 void PF_te_tarexplosion (void)
1983 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1984 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1991 void PF_te_wizspike (void)
1993 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1994 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1996 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1997 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1998 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2001 void PF_te_knightspike (void)
2003 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2004 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2006 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2007 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2008 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2011 void PF_te_lavasplash (void)
2013 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2014 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2016 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2017 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2018 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2021 void PF_te_teleport (void)
2023 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2024 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2026 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2028 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2031 void PF_te_explosion2 (void)
2033 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2034 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2036 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2037 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2038 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2040 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2041 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2044 void PF_te_lightning1 (void)
2046 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2047 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2049 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2052 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2055 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2056 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2060 void PF_te_lightning2 (void)
2062 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2063 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2065 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2067 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2068 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2069 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2071 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2072 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2076 void PF_te_lightning3 (void)
2078 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2079 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2081 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2083 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2084 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2085 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2087 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2088 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2089 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2092 void PF_te_beam (void)
2094 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2095 MSG_WriteByte(&sv.datagram, TE_BEAM);
2097 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2099 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2100 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2101 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2103 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2104 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2105 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2108 void PF_te_plasmaburn (void)
2110 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2111 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2112 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2113 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2114 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2117 void PF_te_flamejet (void)
2119 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2120 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2122 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2123 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2124 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2126 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2127 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2128 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2130 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2133 void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2136 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2138 bestdist = 1000000000;
2140 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2142 // clip original point to each triangle of the surface and find the
2143 // triangle that is closest
2144 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2145 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2146 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2147 TriangleNormal(v[0], v[1], v[2], facenormal);
2148 VectorNormalize(facenormal);
2149 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2150 VectorMA(p, offsetdist, facenormal, temp);
2151 for (j = 0, k = 2;j < 3;k = j, j++)
2153 VectorSubtract(v[k], v[j], edgenormal);
2154 CrossProduct(edgenormal, facenormal, sidenormal);
2155 VectorNormalize(sidenormal);
2156 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2158 VectorMA(temp, offsetdist, sidenormal, temp);
2160 dist = VectorDistance2(temp, p);
2161 if (bestdist > dist)
2164 VectorCopy(temp, out);
2169 static model_t *getmodel(prvm_edict_t *ed)
2172 if (!ed || ed->priv.server->free)
2174 modelindex = (int)ed->fields.server->modelindex;
2175 if (modelindex < 1 || modelindex >= MAX_MODELS)
2177 return sv.models[modelindex];
2180 static msurface_t *getsurface(model_t *model, int surfacenum)
2182 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2184 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2188 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2189 void PF_getsurfacenumpoints(void)
2192 msurface_t *surface;
2193 // return 0 if no such surface
2194 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2196 PRVM_G_FLOAT(OFS_RETURN) = 0;
2200 // note: this (incorrectly) assumes it is a simple polygon
2201 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2203 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2204 void PF_getsurfacepoint(void)
2208 msurface_t *surface;
2210 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2211 ed = PRVM_G_EDICT(OFS_PARM0);
2212 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2214 // note: this (incorrectly) assumes it is a simple polygon
2215 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2216 if (pointnum < 0 || pointnum >= surface->num_vertices)
2218 // FIXME: implement rotation/scaling
2219 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2221 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2222 void PF_getsurfacenormal(void)
2225 msurface_t *surface;
2227 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2228 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2230 // FIXME: implement rotation/scaling
2231 // note: this (incorrectly) assumes it is a simple polygon
2232 // note: this only returns the first triangle, so it doesn't work very
2233 // well for curved surfaces or arbitrary meshes
2234 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);
2235 VectorNormalize(normal);
2236 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2238 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2239 void PF_getsurfacetexture(void)
2242 msurface_t *surface;
2243 PRVM_G_INT(OFS_RETURN) = 0;
2244 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2246 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
2248 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2249 void PF_getsurfacenearpoint(void)
2251 int surfacenum, best;
2253 vec_t dist, bestdist;
2256 msurface_t *surface;
2258 PRVM_G_FLOAT(OFS_RETURN) = -1;
2259 ed = PRVM_G_EDICT(OFS_PARM0);
2260 point = PRVM_G_VECTOR(OFS_PARM1);
2262 if (!ed || ed->priv.server->free)
2264 model = getmodel(ed);
2265 if (!model || !model->num_surfaces)
2268 // FIXME: implement rotation/scaling
2269 VectorSubtract(point, ed->fields.server->origin, p);
2271 bestdist = 1000000000;
2272 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2274 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2275 // first see if the nearest point on the surface's box is closer than the previous match
2276 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2277 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2278 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2279 dist = VectorLength2(clipped);
2280 if (dist < bestdist)
2282 // it is, check the nearest point on the actual geometry
2283 clippointtosurface(model, surface, p, clipped);
2284 VectorSubtract(clipped, p, clipped);
2285 dist += VectorLength2(clipped);
2286 if (dist < bestdist)
2288 // that's closer too, store it as the best match
2294 PRVM_G_FLOAT(OFS_RETURN) = best;
2296 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2297 void PF_getsurfaceclippedpoint(void)
2301 msurface_t *surface;
2303 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2304 ed = PRVM_G_EDICT(OFS_PARM0);
2305 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2307 // FIXME: implement rotation/scaling
2308 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2309 clippointtosurface(model, surface, p, out);
2310 // FIXME: implement rotation/scaling
2311 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2314 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2315 //this function originally written by KrimZon, made shorter by LordHavoc
2316 void PF_clientcommand (void)
2318 client_t *temp_client;
2321 //find client for this entity
2322 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2323 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2325 Con_Print("PF_clientcommand: entity is not a client\n");
2329 temp_client = host_client;
2330 host_client = svs.clients + i;
2331 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2332 host_client = temp_client;
2335 //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)
2336 void PF_setattachment (void)
2338 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2339 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2340 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2345 if (e == prog->edicts)
2347 VM_Warning("setattachment: can not modify world entity\n");
2350 if (e->priv.server->free)
2352 VM_Warning("setattachment: can not modify free entity\n");
2356 if (tagentity == NULL)
2357 tagentity = prog->edicts;
2359 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2361 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2363 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2366 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2368 modelindex = (int)tagentity->fields.server->modelindex;
2369 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2371 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2373 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);
2376 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));
2380 /////////////////////////////////////////
2381 // DP_MD3_TAGINFO extension coded by VorteX
2383 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2388 i = (int)e->fields.server->modelindex;
2389 if (i < 1 || i >= MAX_MODELS)
2391 model = sv.models[i];
2393 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2396 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2398 float scale = PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float;
2402 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);
2404 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);
2407 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2413 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2414 && (model = sv.models[(int)ent->fields.server->modelindex])
2415 && model->animscenes)
2417 // if model has wrong frame, engine automatically switches to model first frame
2418 frame = (int)ent->fields.server->frame;
2419 if (frame < 0 || frame >= model->numframes)
2421 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2423 *out = identitymatrix;
2427 // Warnings/errors code:
2428 // 0 - normal (everything all-right)
2431 // 3 - null or non-precached model
2432 // 4 - no tags with requested index
2433 // 5 - runaway loop at attachment chain
2434 extern cvar_t cl_bob;
2435 extern cvar_t cl_bobcycle;
2436 extern cvar_t cl_bobup;
2437 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2441 int modelindex, attachloop;
2442 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2445 *out = identitymatrix; // warnings and errors return identical matrix
2447 if (ent == prog->edicts)
2449 if (ent->priv.server->free)
2452 modelindex = (int)ent->fields.server->modelindex;
2453 if (modelindex <= 0 || modelindex > MAX_MODELS)
2456 model = sv.models[modelindex];
2458 tagmatrix = identitymatrix;
2459 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2463 if (attachloop >= 256) // prevent runaway looping
2465 // apply transformation by child's tagindex on parent entity and then
2466 // by parent entity itself
2467 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2468 if (ret && attachloop == 0)
2470 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2471 SV_GetEntityMatrix(ent, &entitymatrix, false);
2472 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2473 // next iteration we process the parent entity
2474 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2476 tagindex = (int)PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
2477 ent = PRVM_EDICT_NUM(val->edict);
2484 // RENDER_VIEWMODEL magic
2485 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2487 Matrix4x4_Copy(&tagmatrix, out);
2488 ent = PRVM_EDICT_NUM(val->edict);
2490 SV_GetEntityMatrix(ent, &entitymatrix, true);
2491 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2494 // Cl_bob, ported from rendering code
2495 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2498 // LordHavoc: this code is *weird*, but not replacable (I think it
2499 // should be done in QC on the server, but oh well, quake is quake)
2500 // LordHavoc: figured out bobup: the time at which the sin is at 180
2501 // degrees (which allows lengthening or squishing the peak or valley)
2502 cycle = sv.time/cl_bobcycle.value;
2503 cycle -= (int)cycle;
2504 if (cycle < cl_bobup.value)
2505 cycle = sin(M_PI * cycle / cl_bobup.value);
2507 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2508 // bob is proportional to velocity in the xy plane
2509 // (don't count Z, or jumping messes it up)
2510 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;
2511 bob = bob*0.3 + bob*0.7*cycle;
2512 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2519 //float(entity ent, string tagname) gettagindex;
2521 void PF_gettagindex (void)
2523 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2524 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2525 int modelindex, tag_index;
2527 if (ent == prog->edicts)
2529 VM_Warning("gettagindex: can't affect world entity\n");
2532 if (ent->priv.server->free)
2534 VM_Warning("gettagindex: can't affect free entity\n");
2538 modelindex = (int)ent->fields.server->modelindex;
2540 if (modelindex <= 0 || modelindex > MAX_MODELS)
2541 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2544 tag_index = SV_GetTagIndex(ent, tag_name);
2546 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2548 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2551 //vector(entity ent, float tagindex) gettaginfo;
2552 void PF_gettaginfo (void)
2554 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2555 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2556 matrix4x4_t tag_matrix;
2559 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2560 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2565 VM_Warning("gettagindex: can't affect world entity\n");
2568 VM_Warning("gettagindex: can't affect free entity\n");
2571 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2574 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2577 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2582 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2583 void PF_dropclient (void)
2586 client_t *oldhostclient;
2587 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2588 if (clientnum < 0 || clientnum >= svs.maxclients)
2590 VM_Warning("dropclient: not a client\n");
2593 if (!svs.clients[clientnum].active)
2595 VM_Warning("dropclient: that client slot is not connected\n");
2598 oldhostclient = host_client;
2599 host_client = svs.clients + clientnum;
2600 SV_DropClient(false);
2601 host_client = oldhostclient;
2604 //entity() spawnclient (DP_SV_BOTCLIENT)
2605 void PF_spawnclient (void)
2609 prog->xfunction->builtinsprofile += 2;
2611 for (i = 0;i < svs.maxclients;i++)
2613 if (!svs.clients[i].active)
2615 prog->xfunction->builtinsprofile += 100;
2616 SV_ConnectClient (i, NULL);
2617 // this has to be set or else ClientDisconnect won't be called
2618 // we assume the qc will call ClientConnect...
2619 svs.clients[i].clientconnectcalled = true;
2620 ed = PRVM_EDICT_NUM(i + 1);
2624 VM_RETURN_EDICT(ed);
2627 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2628 void PF_clienttype (void)
2631 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2632 if (clientnum < 0 || clientnum >= svs.maxclients)
2633 PRVM_G_FLOAT(OFS_RETURN) = 3;
2634 else if (!svs.clients[clientnum].active)
2635 PRVM_G_FLOAT(OFS_RETURN) = 0;
2636 else if (svs.clients[clientnum].netconnection)
2637 PRVM_G_FLOAT(OFS_RETURN) = 1;
2639 PRVM_G_FLOAT(OFS_RETURN) = 2;
2642 void PF_edict_num (void)
2644 VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0)));
2647 prvm_builtin_t vm_sv_builtins[] = {
2649 PF_makevectors, // #1 void(vector ang) makevectors
2650 PF_setorigin, // #2 void(entity e, vector o) setorigin
2651 PF_setmodel, // #3 void(entity e, string m) setmodel
2652 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2653 NULL, // #5 void(entity e, vector min, vector max) setabssize
2654 VM_break, // #6 void() break
2655 VM_random, // #7 float() random
2656 PF_sound, // #8 void(entity e, float chan, string samp) sound
2657 VM_normalize, // #9 vector(vector v) normalize
2658 VM_error, // #10 void(string e) error
2659 VM_objerror, // #11 void(string e) objerror
2660 VM_vlen, // #12 float(vector v) vlen
2661 VM_vectoyaw, // #13 float(vector v) vectoyaw
2662 VM_spawn, // #14 entity() spawn
2663 VM_remove, // #15 void(entity e) remove
2664 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2665 PF_checkclient, // #17 entity() clientlist
2666 VM_find, // #18 entity(entity start, .string fld, string match) find
2667 PF_precache_sound, // #19 void(string s) precache_sound
2668 PF_precache_model, // #20 void(string s) precache_model
2669 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2670 PF_findradius, // #22 entity(vector org, float rad) findradius
2671 VM_bprint, // #23 void(string s) bprint
2672 PF_sprint, // #24 void(entity client, string s) sprint
2673 VM_dprint, // #25 void(string s) dprint
2674 VM_ftos, // #26 void(string s) ftos
2675 VM_vtos, // #27 void(string s) vtos
2676 VM_coredump, // #28 void() coredump
2677 VM_traceon, // #29 void() traceon
2678 VM_traceoff, // #30 void() traceoff
2679 VM_eprint, // #31 void(entity e) eprint
2680 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2682 PF_droptofloor, // #34 float() droptofloor
2683 PF_lightstyle, // #35 void(float style, string value) lightstyle
2684 VM_rint, // #36 float(float v) rint
2685 VM_floor, // #37 float(float v) floor
2686 VM_ceil, // #38 float(float v) ceil
2688 PF_checkbottom, // #40 float(entity e) checkbottom
2689 PF_pointcontents, // #41 float(vector v) pointcontents
2691 VM_fabs, // #43 float(float f) fabs
2692 PF_aim, // #44 vector(entity e, float speed) aim
2693 VM_cvar, // #45 float(string s) cvar
2694 VM_localcmd, // #46 void(string s) localcmd
2695 VM_nextent, // #47 entity(entity e) nextent
2696 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2697 PF_changeyaw, // #49 void() ChangeYaw
2699 VM_vectoangles, // #51 vector(vector v) vectoangles
2700 PF_WriteByte, // #52 void(float to, float f) WriteByte
2701 PF_WriteChar, // #53 void(float to, float f) WriteChar
2702 PF_WriteShort, // #54 void(float to, float f) WriteShort
2703 PF_WriteLong, // #55 void(float to, float f) WriteLong
2704 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2705 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2706 PF_WriteString, // #58 void(float to, string s) WriteString
2707 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2708 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2709 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2710 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2711 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2712 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2713 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2715 SV_MoveToGoal, // #67 void(float step) movetogoal
2716 PF_precache_file, // #68 string(string s) precache_file
2717 PF_makestatic, // #69 void(entity e) makestatic
2718 VM_changelevel, // #70 void(string s) changelevel
2720 VM_cvar_set, // #72 void(string var, string val) cvar_set
2721 PF_centerprint, // #73 void(entity client, strings) centerprint
2722 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2723 PF_precache_model, // #75 string(string s) precache_model2
2724 PF_precache_sound, // #76 string(string s) precache_sound2
2725 PF_precache_file, // #77 string(string s) precache_file2
2726 PF_setspawnparms, // #78 void(entity e) setspawnparms
2729 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2738 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2739 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2740 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2741 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2742 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2743 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2744 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2745 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2746 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2747 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2758 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2759 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2760 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2761 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2762 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2763 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2764 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2765 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2766 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2767 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2768 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2769 // FTEQW range #200-#299
2788 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2798 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2799 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2800 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2801 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2802 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2803 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2804 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2805 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2806 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2807 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2808 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2809 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2810 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2811 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2812 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2813 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2814 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2815 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2816 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2817 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2818 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2819 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2820 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2821 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2822 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2823 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2824 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2825 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2826 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2827 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2828 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2829 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2830 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2831 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2832 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2833 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2834 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2835 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2836 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2837 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2838 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2839 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2840 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2841 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2842 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2843 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2844 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2845 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2846 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2847 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2848 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2849 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2850 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2851 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2852 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2853 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2854 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2855 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2856 PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2858 PF_edict_num, // #459 entity(float num) (??)
2859 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2860 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2861 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2862 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2863 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2864 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2865 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2866 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2867 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2868 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2869 PF_SV_AddStat, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2870 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
2871 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
2872 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
2873 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
2874 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
2875 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
2876 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
2879 e10, e10 // #480-499 (LordHavoc)
2882 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2884 void VM_SV_Cmd_Init(void)
2889 void VM_SV_Cmd_Reset(void)