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 "
71 "DP_QC_UNLIMITEDTEMPSTRINGS "
74 "DP_QC_TRACE_MOVETYPE_HITMODEL "
75 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
76 "DP_QC_VECTORVECTORS "
82 "DP_SND_DIRECTIONLESSATTNNONE "
91 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
92 "DP_SV_DRAWONLYTOCLIENT "
95 "DP_SV_ENTITYCONTENTSTRANSITION "
96 "DP_SV_NODRAWTOCLIENT "
98 "DP_SV_PLAYERPHYSICS "
99 "DP_SV_PRECACHEANYTIME "
101 "DP_SV_ROTATINGBMODEL "
104 "DP_SV_WRITEUNTERMINATEDSTRING "
108 "DP_TE_EXPLOSIONRGB "
110 "DP_TE_PARTICLECUBE "
111 "DP_TE_PARTICLERAIN "
112 "DP_TE_PARTICLESNOW "
114 "DP_TE_QUADEFFECTS1 "
117 "DP_TE_STANDARDEFFECTBUILTINS "
118 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
121 //"EXT_CSQC " // not ready yet
123 "KRIMZON_SV_PARSECLIENTCOMMAND "
127 "PRYDON_CLIENTCURSOR "
128 "TENEBRAE_GFX_DLIGHTS "
130 "NEXUIZ_PLAYERMODEL "
137 Writes new values for v_forward, v_up, and v_right based on angles
141 void PF_makevectors (void)
143 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
150 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.
152 setorigin (entity, origin)
155 void PF_setorigin (void)
160 e = PRVM_G_EDICT(OFS_PARM0);
161 if (e == prog->edicts)
163 VM_Warning("setorigin: can not modify world entity\n");
166 if (e->priv.server->free)
168 VM_Warning("setorigin: can not modify free entity\n");
171 org = PRVM_G_VECTOR(OFS_PARM1);
172 VectorCopy (org, e->fields.server->origin);
173 SV_LinkEdict (e, false);
177 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
181 for (i=0 ; i<3 ; i++)
183 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
185 // set derived values
186 VectorCopy (min, e->fields.server->mins);
187 VectorCopy (max, e->fields.server->maxs);
188 VectorSubtract (max, min, e->fields.server->size);
190 SV_LinkEdict (e, false);
197 the size box is rotated by the current angle
198 LordHavoc: no it isn't...
200 setsize (entity, minvector, maxvector)
203 void PF_setsize (void)
208 e = PRVM_G_EDICT(OFS_PARM0);
209 if (e == prog->edicts)
211 VM_Warning("setsize: can not modify world entity\n");
214 if (e->priv.server->free)
216 VM_Warning("setsize: can not modify free entity\n");
219 min = PRVM_G_VECTOR(OFS_PARM1);
220 max = PRVM_G_VECTOR(OFS_PARM2);
221 SetMinMaxSize (e, min, max, false);
229 setmodel(entity, model)
232 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
233 void PF_setmodel (void)
239 e = PRVM_G_EDICT(OFS_PARM0);
240 if (e == prog->edicts)
242 VM_Warning("setmodel: can not modify world entity\n");
245 if (e->priv.server->free)
247 VM_Warning("setmodel: can not modify free entity\n");
250 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
251 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
252 e->fields.server->modelindex = i;
258 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
259 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
261 SetMinMaxSize (e, quakemins, quakemaxs, true);
264 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
271 single print to a specific client
273 sprint(clientent, value)
276 void PF_sprint (void)
280 char string[VM_STRINGTEMP_LENGTH];
282 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
284 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
286 VM_Warning("tried to centerprint to a non-client\n");
290 client = svs.clients + entnum-1;
291 if (!client->netconnection)
294 VM_VarString(1, string, sizeof(string));
295 MSG_WriteChar(&client->netconnection->message,svc_print);
296 MSG_WriteString(&client->netconnection->message, string);
304 single print to a specific client
306 centerprint(clientent, value)
309 void PF_centerprint (void)
313 char string[VM_STRINGTEMP_LENGTH];
315 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
317 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
319 VM_Warning("tried to centerprint to a non-client\n");
323 client = svs.clients + entnum-1;
324 if (!client->netconnection)
327 VM_VarString(1, string, sizeof(string));
328 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
329 MSG_WriteString(&client->netconnection->message, string);
336 particle(origin, color, count)
339 void PF_particle (void)
345 org = PRVM_G_VECTOR(OFS_PARM0);
346 dir = PRVM_G_VECTOR(OFS_PARM1);
347 color = PRVM_G_FLOAT(OFS_PARM2);
348 count = PRVM_G_FLOAT(OFS_PARM3);
349 SV_StartParticle (org, dir, (int)color, (int)count);
359 void PF_ambientsound (void)
363 float vol, attenuation;
366 pos = PRVM_G_VECTOR (OFS_PARM0);
367 samp = PRVM_G_STRING(OFS_PARM1);
368 vol = PRVM_G_FLOAT(OFS_PARM2);
369 attenuation = PRVM_G_FLOAT(OFS_PARM3);
371 // check to see if samp was properly precached
372 soundnum = SV_SoundIndex(samp, 1);
380 // add an svc_spawnambient command to the level signon packet
383 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
385 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
387 MSG_WriteVector(&sv.signon, pos, sv.protocol);
390 MSG_WriteShort (&sv.signon, soundnum);
392 MSG_WriteByte (&sv.signon, soundnum);
394 MSG_WriteByte (&sv.signon, (int)(vol*255));
395 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
403 Each entity can have eight independant sound sources, like voice,
406 Channel 0 is an auto-allocate channel, the others override anything
407 already running on that entity/channel pair.
409 An attenuation of 0 will play full volume everywhere in the level.
410 Larger attenuations will drop off.
418 prvm_edict_t *entity;
422 entity = PRVM_G_EDICT(OFS_PARM0);
423 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
424 sample = PRVM_G_STRING(OFS_PARM2);
425 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
426 attenuation = PRVM_G_FLOAT(OFS_PARM4);
428 if (volume < 0 || volume > 255)
430 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
434 if (attenuation < 0 || attenuation > 4)
436 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
440 if (channel < 0 || channel > 7)
442 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
446 SV_StartSound (entity, channel, sample, volume, attenuation);
453 Used for use tracing and shot targeting
454 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
455 if the tryents flag is set.
457 traceline (vector1, vector2, tryents)
460 void PF_traceline (void)
468 prog->xfunction->builtinsprofile += 30;
470 v1 = PRVM_G_VECTOR(OFS_PARM0);
471 v2 = PRVM_G_VECTOR(OFS_PARM1);
472 move = (int)PRVM_G_FLOAT(OFS_PARM2);
473 ent = PRVM_G_EDICT(OFS_PARM3);
475 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]))
476 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));
478 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
480 prog->globals.server->trace_allsolid = trace.allsolid;
481 prog->globals.server->trace_startsolid = trace.startsolid;
482 prog->globals.server->trace_fraction = trace.fraction;
483 prog->globals.server->trace_inwater = trace.inwater;
484 prog->globals.server->trace_inopen = trace.inopen;
485 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
486 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
487 prog->globals.server->trace_plane_dist = trace.plane.dist;
489 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
491 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
492 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
493 val->_float = trace.startsupercontents;
494 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
495 val->_float = trace.hitsupercontents;
496 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
497 val->_float = trace.hitq3surfaceflags;
498 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
500 if (trace.hittexture)
501 val->string = PRVM_SetTempString(trace.hittexture->name);
512 Used for use tracing and shot targeting
513 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
514 if the tryents flag is set.
516 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
519 // LordHavoc: added this for my own use, VERY useful, similar to traceline
520 void PF_tracebox (void)
522 float *v1, *v2, *m1, *m2;
528 prog->xfunction->builtinsprofile += 30;
530 v1 = PRVM_G_VECTOR(OFS_PARM0);
531 m1 = PRVM_G_VECTOR(OFS_PARM1);
532 m2 = PRVM_G_VECTOR(OFS_PARM2);
533 v2 = PRVM_G_VECTOR(OFS_PARM3);
534 move = (int)PRVM_G_FLOAT(OFS_PARM4);
535 ent = PRVM_G_EDICT(OFS_PARM5);
537 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]))
538 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));
540 trace = SV_Move (v1, m1, m2, v2, move, ent);
542 prog->globals.server->trace_allsolid = trace.allsolid;
543 prog->globals.server->trace_startsolid = trace.startsolid;
544 prog->globals.server->trace_fraction = trace.fraction;
545 prog->globals.server->trace_inwater = trace.inwater;
546 prog->globals.server->trace_inopen = trace.inopen;
547 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
548 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
549 prog->globals.server->trace_plane_dist = trace.plane.dist;
551 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
553 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
554 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
555 val->_float = trace.startsupercontents;
556 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
557 val->_float = trace.hitsupercontents;
558 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
559 val->_float = trace.hitq3surfaceflags;
560 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
562 if (trace.hittexture)
563 val->string = PRVM_SetTempString(trace.hittexture->name);
569 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
570 void PF_tracetoss (void)
574 prvm_edict_t *ignore;
577 prog->xfunction->builtinsprofile += 600;
579 ent = PRVM_G_EDICT(OFS_PARM0);
580 if (ent == prog->edicts)
582 VM_Warning("tracetoss: can not use world entity\n");
585 ignore = PRVM_G_EDICT(OFS_PARM1);
587 trace = SV_Trace_Toss (ent, ignore);
589 prog->globals.server->trace_allsolid = trace.allsolid;
590 prog->globals.server->trace_startsolid = trace.startsolid;
591 prog->globals.server->trace_fraction = trace.fraction;
592 prog->globals.server->trace_inwater = trace.inwater;
593 prog->globals.server->trace_inopen = trace.inopen;
594 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
595 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
596 prog->globals.server->trace_plane_dist = trace.plane.dist;
598 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
600 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
601 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
602 val->_float = trace.startsupercontents;
603 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
604 val->_float = trace.hitsupercontents;
605 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
606 val->_float = trace.hitq3surfaceflags;
607 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
609 if (trace.hittexture)
610 val->string = PRVM_SetTempString(trace.hittexture->name);
621 Returns true if the given entity can move to the given position from it's
622 current position by walking or rolling.
624 scalar checkpos (entity, vector)
627 void PF_checkpos (void)
631 //============================================================================
634 unsigned char checkpvs[MAX_MAP_LEAFS/8];
636 int PF_newcheckclient (int check)
642 // cycle to the next one
644 check = bound(1, check, svs.maxclients);
645 if (check == svs.maxclients)
653 prog->xfunction->builtinsprofile++;
655 if (i == svs.maxclients+1)
657 // look up the client's edict
658 ent = PRVM_EDICT_NUM(i);
659 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
660 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
662 // found a valid client (possibly the same one again)
666 // get the PVS for the entity
667 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
669 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
670 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
679 Returns a client (or object that has a client enemy) that would be a
682 If there is more than one valid option, they are cycled each frame
684 If (self.origin + self.viewofs) is not in the PVS of the current target,
685 it is not returned at all.
690 int c_invis, c_notvis;
691 void PF_checkclient (void)
693 prvm_edict_t *ent, *self;
696 // find a new check if on a new frame
697 if (sv.time - sv.lastchecktime >= 0.1)
699 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
700 sv.lastchecktime = sv.time;
703 // return check if it might be visible
704 ent = PRVM_EDICT_NUM(sv.lastcheck);
705 if (ent->priv.server->free || ent->fields.server->health <= 0)
707 VM_RETURN_EDICT(prog->edicts);
711 // if current entity can't possibly see the check entity, return 0
712 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
713 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
714 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
717 VM_RETURN_EDICT(prog->edicts);
721 // might be able to see it
723 VM_RETURN_EDICT(ent);
726 //============================================================================
733 Sends text over to the client's execution buffer
735 stuffcmd (clientent, value, ...)
738 void PF_stuffcmd (void)
742 char string[VM_STRINGTEMP_LENGTH];
744 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
745 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
747 VM_Warning("Can't stuffcmd to a non-client\n");
751 VM_VarString(1, string, sizeof(string));
754 host_client = svs.clients + entnum-1;
755 Host_ClientCommands ("%s", string);
763 Returns a chain of entities that have origins within a spherical area
765 findradius (origin, radius)
768 void PF_findradius (void)
770 prvm_edict_t *ent, *chain;
771 vec_t radius, radius2;
772 vec3_t org, eorg, mins, maxs;
775 prvm_edict_t *touchedicts[MAX_EDICTS];
777 chain = (prvm_edict_t *)prog->edicts;
779 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
780 radius = PRVM_G_FLOAT(OFS_PARM1);
781 radius2 = radius * radius;
783 mins[0] = org[0] - (radius + 1);
784 mins[1] = org[1] - (radius + 1);
785 mins[2] = org[2] - (radius + 1);
786 maxs[0] = org[0] + (radius + 1);
787 maxs[1] = org[1] + (radius + 1);
788 maxs[2] = org[2] + (radius + 1);
789 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
790 if (numtouchedicts > MAX_EDICTS)
792 // this never happens
793 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
794 numtouchedicts = MAX_EDICTS;
796 for (i = 0;i < numtouchedicts;i++)
798 ent = touchedicts[i];
799 prog->xfunction->builtinsprofile++;
800 // Quake did not return non-solid entities but darkplaces does
801 // (note: this is the reason you can't blow up fallen zombies)
802 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
804 // LordHavoc: compare against bounding box rather than center so it
805 // doesn't miss large objects, and use DotProduct instead of Length
806 // for a major speedup
807 VectorSubtract(org, ent->fields.server->origin, eorg);
808 if (sv_gameplayfix_findradiusdistancetobox.integer)
810 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
811 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
812 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
815 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
816 if (DotProduct(eorg, eorg) < radius2)
818 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
823 VM_RETURN_EDICT(chain);
826 void PF_precache_file (void)
827 { // precache_file is only used to copy files with qcc, it does nothing
828 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
832 void PF_precache_sound (void)
834 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
835 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
838 void PF_precache_model (void)
840 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
841 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
848 float(float yaw, float dist) walkmove
851 void PF_walkmove (void)
859 // assume failure if it returns early
860 PRVM_G_FLOAT(OFS_RETURN) = 0;
862 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
863 if (ent == prog->edicts)
865 VM_Warning("walkmove: can not modify world entity\n");
868 if (ent->priv.server->free)
870 VM_Warning("walkmove: can not modify free entity\n");
873 yaw = PRVM_G_FLOAT(OFS_PARM0);
874 dist = PRVM_G_FLOAT(OFS_PARM1);
876 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
879 yaw = yaw*M_PI*2 / 360;
881 move[0] = cos(yaw)*dist;
882 move[1] = sin(yaw)*dist;
885 // save program state, because SV_movestep may call other progs
886 oldf = prog->xfunction;
887 oldself = prog->globals.server->self;
889 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
892 // restore program state
893 prog->xfunction = oldf;
894 prog->globals.server->self = oldself;
904 void PF_droptofloor (void)
910 // assume failure if it returns early
911 PRVM_G_FLOAT(OFS_RETURN) = 0;
913 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
914 if (ent == prog->edicts)
916 VM_Warning("droptofloor: can not modify world entity\n");
919 if (ent->priv.server->free)
921 VM_Warning("droptofloor: can not modify free entity\n");
925 VectorCopy (ent->fields.server->origin, end);
928 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
930 if (trace.fraction != 1 || (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer))
932 if (trace.fraction < 1)
933 VectorCopy (trace.endpos, ent->fields.server->origin);
934 SV_LinkEdict (ent, false);
935 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
936 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
937 PRVM_G_FLOAT(OFS_RETURN) = 1;
938 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
939 ent->priv.server->suspendedinairflag = true;
947 void(float style, string value) lightstyle
950 void PF_lightstyle (void)
957 style = (int)PRVM_G_FLOAT(OFS_PARM0);
958 val = PRVM_G_STRING(OFS_PARM1);
960 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
961 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
964 // change the string in sv
965 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
967 // send message to all clients on this server
968 if (sv.state != ss_active)
971 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
973 if (client->active && client->netconnection)
975 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
976 MSG_WriteChar (&client->netconnection->message,style);
977 MSG_WriteString (&client->netconnection->message, val);
987 void PF_checkbottom (void)
989 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
997 void PF_pointcontents (void)
999 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1006 Pick a vector for the player to shoot along
1007 vector aim(entity, missilespeed)
1012 prvm_edict_t *ent, *check, *bestent;
1013 vec3_t start, dir, end, bestdir;
1016 float dist, bestdist;
1019 // assume failure if it returns early
1020 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1021 // if sv_aim is so high it can't possibly accept anything, skip out early
1022 if (sv_aim.value >= 1)
1025 ent = PRVM_G_EDICT(OFS_PARM0);
1026 if (ent == prog->edicts)
1028 VM_Warning("aim: can not use world entity\n");
1031 if (ent->priv.server->free)
1033 VM_Warning("aim: can not use free entity\n");
1036 speed = PRVM_G_FLOAT(OFS_PARM1);
1038 VectorCopy (ent->fields.server->origin, start);
1041 // try sending a trace straight
1042 VectorCopy (prog->globals.server->v_forward, dir);
1043 VectorMA (start, 2048, dir, end);
1044 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1045 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1046 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1048 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1053 // try all possible entities
1054 VectorCopy (dir, bestdir);
1055 bestdist = sv_aim.value;
1058 check = PRVM_NEXT_EDICT(prog->edicts);
1059 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1061 prog->xfunction->builtinsprofile++;
1062 if (check->fields.server->takedamage != DAMAGE_AIM)
1066 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1067 continue; // don't aim at teammate
1068 for (j=0 ; j<3 ; j++)
1069 end[j] = check->fields.server->origin[j]
1070 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1071 VectorSubtract (end, start, dir);
1072 VectorNormalize (dir);
1073 dist = DotProduct (dir, prog->globals.server->v_forward);
1074 if (dist < bestdist)
1075 continue; // to far to turn
1076 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1077 if (tr.ent == check)
1078 { // can shoot at this one
1086 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1087 dist = DotProduct (dir, prog->globals.server->v_forward);
1088 VectorScale (prog->globals.server->v_forward, dist, end);
1090 VectorNormalize (end);
1091 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1095 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1103 This was a major timewaster in progs, so it was converted to C
1106 void PF_changeyaw (void)
1109 float ideal, current, move, speed;
1111 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1112 if (ent == prog->edicts)
1114 VM_Warning("changeyaw: can not modify world entity\n");
1117 if (ent->priv.server->free)
1119 VM_Warning("changeyaw: can not modify free entity\n");
1122 current = ANGLEMOD(ent->fields.server->angles[1]);
1123 ideal = ent->fields.server->ideal_yaw;
1124 speed = ent->fields.server->yaw_speed;
1126 if (current == ideal)
1128 move = ideal - current;
1129 if (ideal > current)
1150 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1158 void PF_changepitch (void)
1161 float ideal, current, move, speed;
1164 ent = PRVM_G_EDICT(OFS_PARM0);
1165 if (ent == prog->edicts)
1167 VM_Warning("changepitch: can not modify world entity\n");
1170 if (ent->priv.server->free)
1172 VM_Warning("changepitch: can not modify free entity\n");
1175 current = ANGLEMOD( ent->fields.server->angles[0] );
1176 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1177 ideal = val->_float;
1180 VM_Warning("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1183 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1184 speed = val->_float;
1187 VM_Warning("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1191 if (current == ideal)
1193 move = ideal - current;
1194 if (ideal > current)
1215 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1219 ===============================================================================
1223 ===============================================================================
1226 #define MSG_BROADCAST 0 // unreliable to all
1227 #define MSG_ONE 1 // reliable to one (msg_entity)
1228 #define MSG_ALL 2 // reliable to all
1229 #define MSG_INIT 3 // write to the init string
1230 #define MSG_ENTITY 5
1232 sizebuf_t *WriteDest (void)
1237 extern sizebuf_t *sv2csqcbuf;
1239 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1243 return &sv.datagram;
1246 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1247 entnum = PRVM_NUM_FOR_EDICT(ent);
1248 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1250 VM_Warning ("WriteDest: tried to write to non-client\n");
1251 return &sv.reliable_datagram;
1254 return &svs.clients[entnum-1].netconnection->message;
1257 VM_Warning ("WriteDest: bad destination\n");
1259 return &sv.reliable_datagram;
1271 void PF_WriteByte (void)
1273 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1276 void PF_WriteChar (void)
1278 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1281 void PF_WriteShort (void)
1283 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1286 void PF_WriteLong (void)
1288 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1291 void PF_WriteAngle (void)
1293 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1296 void PF_WriteCoord (void)
1298 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1301 void PF_WriteString (void)
1303 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1306 void PF_WriteUnterminatedString (void)
1308 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1312 void PF_WriteEntity (void)
1314 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1317 //////////////////////////////////////////////////////////
1319 void PF_makestatic (void)
1324 ent = PRVM_G_EDICT(OFS_PARM0);
1325 if (ent == prog->edicts)
1327 VM_Warning("makestatic: can not modify world entity\n");
1330 if (ent->priv.server->free)
1332 VM_Warning("makestatic: can not modify free entity\n");
1337 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1342 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1343 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1344 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1348 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1349 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1350 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1353 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1354 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1355 for (i=0 ; i<3 ; i++)
1357 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1358 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1361 // throw the entity away now
1365 //=============================================================================
1372 void PF_setspawnparms (void)
1378 ent = PRVM_G_EDICT(OFS_PARM0);
1379 i = PRVM_NUM_FOR_EDICT(ent);
1380 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1382 Con_Print("tried to setspawnparms on a non-client\n");
1386 // copy spawn parms out of the client_t
1387 client = svs.clients + i-1;
1388 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1389 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1396 Returns a color vector indicating the lighting at the requested point.
1398 (Internal Operation note: actually measures the light beneath the point, just like
1399 the model lighting on the client)
1404 void PF_getlight (void)
1406 vec3_t ambientcolor, diffusecolor, diffusenormal;
1408 p = PRVM_G_VECTOR(OFS_PARM0);
1409 VectorClear(ambientcolor);
1410 VectorClear(diffusecolor);
1411 VectorClear(diffusenormal);
1412 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1413 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1414 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1417 void PF_registercvar (void)
1419 const char *name, *value;
1420 name = PRVM_G_STRING(OFS_PARM0);
1421 value = PRVM_G_STRING(OFS_PARM1);
1422 PRVM_G_FLOAT(OFS_RETURN) = 0;
1424 // first check to see if it has already been defined
1425 if (Cvar_FindVar (name))
1428 // check for overlap with a command
1429 if (Cmd_Exists (name))
1431 VM_Warning("PF_registercvar: %s is a command\n", name);
1435 Cvar_Get(name, value, 0);
1437 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1442 unsigned char type; // 1/2/8 or other value if isn't used
1446 static autosentstat_t *vm_autosentstats = NULL; //[515]: it starts from 0, not 32
1447 static int vm_autosentstats_last;
1449 void VM_AutoSentStats_Clear (void)
1451 if(vm_autosentstats)
1453 Z_Free(vm_autosentstats);
1454 vm_autosentstats = NULL;
1455 vm_autosentstats_last = -1;
1459 //[515]: add check if even bigger ? "try to use two stats, cause it's too big" ?
1460 #define VM_SENDSTAT(a,b,c)\
1463 if((c)==(unsigned char)(c))\
1465 MSG_WriteByte((a), svc_updatestatubyte);\
1466 MSG_WriteByte((a), (b));\
1467 MSG_WriteByte((a), (c));\
1471 MSG_WriteByte((a), svc_updatestat);\
1472 MSG_WriteByte((a), (b));\
1473 MSG_WriteLong((a), (c));\
1477 void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1489 if(!vm_autosentstats)
1492 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);
1494 for(i=0; i<vm_autosentstats_last+1 ;i++)
1496 if(!vm_autosentstats[i].type)
1498 switch(vm_autosentstats[i].type)
1502 t = PRVM_E_STRING(ent, vm_autosentstats[i].fieldoffset);
1510 stats[i+32] = si[0];
1511 stats[i+33] = si[1];
1512 stats[i+34] = si[2];
1513 stats[i+35] = si[3];
1517 VM_SENDSTAT(msg, i+32, si[0]);
1518 VM_SENDSTAT(msg, i+33, si[1]);
1519 VM_SENDSTAT(msg, i+34, si[2]);
1520 VM_SENDSTAT(msg, i+35, si[3]);
1526 k.f = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1527 k.i = LittleLong (k.i);
1531 VM_SENDSTAT(msg, i+32, k.i);
1535 v = (int)PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1539 VM_SENDSTAT(msg, i+32, v);
1547 // void(float index, float type, .void field) SV_AddStat = #470;
1548 // Set up an auto-sent player stat.
1549 // Client's get thier own fields sent to them. Index may not be less than 32.
1550 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1551 // 1: string (4 stats carrying a total of 16 charactures)
1552 // 2: float (one stat, float converted to an integer for transportation)
1553 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1554 void PF_SV_AddStat (void)
1559 if(!vm_autosentstats)
1561 vm_autosentstats = (autosentstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(autosentstat_t));
1562 if(!vm_autosentstats)
1564 VM_Warning("PF_SV_AddStat: not enough memory\n");
1568 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1569 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1570 off = PRVM_G_INT (OFS_PARM2);
1575 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1578 if(i >= (MAX_CL_STATS-32))
1580 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1583 if(i > (MAX_CL_STATS-32-4) && type == 1)
1585 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1588 vm_autosentstats[i].type = type;
1589 vm_autosentstats[i].fieldoffset = off;
1590 if(vm_autosentstats_last < i)
1591 vm_autosentstats_last = i;
1598 copies data from one entity to another
1600 copyentity(src, dst)
1603 void PF_copyentity (void)
1605 prvm_edict_t *in, *out;
1606 in = PRVM_G_EDICT(OFS_PARM0);
1607 if (in == prog->edicts)
1609 VM_Warning("copyentity: can not read world entity\n");
1612 if (in->priv.server->free)
1614 VM_Warning("copyentity: can not read free entity\n");
1617 out = PRVM_G_EDICT(OFS_PARM1);
1618 if (out == prog->edicts)
1620 VM_Warning("copyentity: can not modify world entity\n");
1623 if (out->priv.server->free)
1625 VM_Warning("copyentity: can not modify free entity\n");
1628 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1636 sets the color of a client and broadcasts the update to all connected clients
1638 setcolor(clientent, value)
1641 void PF_setcolor (void)
1647 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1648 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1650 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1652 Con_Print("tried to setcolor a non-client\n");
1656 client = svs.clients + entnum-1;
1659 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1661 client->edict->fields.server->team = (i & 15) + 1;
1664 if (client->old_colors != client->colors)
1666 client->old_colors = client->colors;
1667 // send notification to all clients
1668 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1669 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1670 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1678 effect(origin, modelname, startframe, framecount, framerate)
1681 void PF_effect (void)
1685 s = PRVM_G_STRING(OFS_PARM1);
1688 VM_Warning("effect: no model specified\n");
1692 i = SV_ModelIndex(s, 1);
1695 VM_Warning("effect: model not precached\n");
1699 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1701 VM_Warning("effect: framecount < 1\n");
1705 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1707 VM_Warning("effect: framerate < 1\n");
1711 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));
1714 void PF_te_blood (void)
1716 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1718 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1719 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1721 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1722 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1723 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1725 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1726 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1727 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1729 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1732 void PF_te_bloodshower (void)
1734 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1736 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1737 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1739 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1740 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1741 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1743 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1744 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1745 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1747 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1749 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1752 void PF_te_explosionrgb (void)
1754 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1755 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1757 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1758 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1759 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1761 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1762 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1763 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1766 void PF_te_particlecube (void)
1768 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1770 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1771 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1773 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1774 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1775 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1777 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1778 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1779 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1781 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1782 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1783 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1785 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1787 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1788 // gravity true/false
1789 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1791 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1794 void PF_te_particlerain (void)
1796 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1798 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1799 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1801 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1802 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1803 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1805 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1809 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1810 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1813 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1815 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1818 void PF_te_particlesnow (void)
1820 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1822 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1823 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1825 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1826 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1827 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1830 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1831 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1833 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1834 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1835 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1837 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1839 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1842 void PF_te_spark (void)
1844 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1846 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1847 MSG_WriteByte(&sv.datagram, TE_SPARK);
1849 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1850 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1851 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1853 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1854 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1855 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1857 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1860 void PF_te_gunshotquad (void)
1862 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1863 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1865 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1866 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1870 void PF_te_spikequad (void)
1872 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1873 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
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_superspikequad (void)
1882 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1883 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
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_explosionquad (void)
1892 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1893 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
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_smallflash (void)
1902 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1903 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
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_customflash (void)
1912 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1914 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1915 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1917 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1918 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1919 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1921 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1923 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1925 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1926 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1927 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1930 void PF_te_gunshot (void)
1932 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1933 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1936 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1940 void PF_te_spike (void)
1942 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1943 MSG_WriteByte(&sv.datagram, TE_SPIKE);
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_superspike (void)
1952 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1953 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
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_explosion (void)
1962 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1963 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
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_tarexplosion (void)
1972 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1973 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
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_wizspike (void)
1982 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1983 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
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_knightspike (void)
1992 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1993 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
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_lavasplash (void)
2002 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2003 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
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_teleport (void)
2012 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2013 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
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_explosion2 (void)
2022 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2023 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
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);
2029 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2030 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2033 void PF_te_lightning1 (void)
2035 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2036 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2038 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2040 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2041 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2042 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2044 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2045 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2046 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2049 void PF_te_lightning2 (void)
2051 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2052 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2054 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2056 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2058 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2060 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2061 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2062 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2065 void PF_te_lightning3 (void)
2067 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2068 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2070 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2072 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2074 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2076 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2077 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2078 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2081 void PF_te_beam (void)
2083 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2084 MSG_WriteByte(&sv.datagram, TE_BEAM);
2086 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2088 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2089 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2090 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2092 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2093 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2094 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2097 void PF_te_plasmaburn (void)
2099 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2100 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2101 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2102 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2103 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2106 void PF_te_flamejet (void)
2108 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2109 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
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);
2115 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2116 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2117 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2119 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2122 void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2125 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2127 bestdist = 1000000000;
2129 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2131 // clip original point to each triangle of the surface and find the
2132 // triangle that is closest
2133 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2134 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2135 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2136 TriangleNormal(v[0], v[1], v[2], facenormal);
2137 VectorNormalize(facenormal);
2138 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2139 VectorMA(p, offsetdist, facenormal, temp);
2140 for (j = 0, k = 2;j < 3;k = j, j++)
2142 VectorSubtract(v[k], v[j], edgenormal);
2143 CrossProduct(edgenormal, facenormal, sidenormal);
2144 VectorNormalize(sidenormal);
2145 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2147 VectorMA(temp, offsetdist, sidenormal, temp);
2149 dist = VectorDistance2(temp, p);
2150 if (bestdist > dist)
2153 VectorCopy(temp, out);
2158 static model_t *getmodel(prvm_edict_t *ed)
2161 if (!ed || ed->priv.server->free)
2163 modelindex = (int)ed->fields.server->modelindex;
2164 if (modelindex < 1 || modelindex >= MAX_MODELS)
2166 return sv.models[modelindex];
2169 static msurface_t *getsurface(model_t *model, int surfacenum)
2171 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2173 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2177 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2178 void PF_getsurfacenumpoints(void)
2181 msurface_t *surface;
2182 // return 0 if no such surface
2183 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2185 PRVM_G_FLOAT(OFS_RETURN) = 0;
2189 // note: this (incorrectly) assumes it is a simple polygon
2190 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2192 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2193 void PF_getsurfacepoint(void)
2197 msurface_t *surface;
2199 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2200 ed = PRVM_G_EDICT(OFS_PARM0);
2201 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2203 // note: this (incorrectly) assumes it is a simple polygon
2204 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2205 if (pointnum < 0 || pointnum >= surface->num_vertices)
2207 // FIXME: implement rotation/scaling
2208 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2210 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2211 void PF_getsurfacenormal(void)
2214 msurface_t *surface;
2216 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2217 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2219 // FIXME: implement rotation/scaling
2220 // note: this (incorrectly) assumes it is a simple polygon
2221 // note: this only returns the first triangle, so it doesn't work very
2222 // well for curved surfaces or arbitrary meshes
2223 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);
2224 VectorNormalize(normal);
2225 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2227 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2228 void PF_getsurfacetexture(void)
2231 msurface_t *surface;
2232 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2233 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2235 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2237 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2238 void PF_getsurfacenearpoint(void)
2240 int surfacenum, best;
2242 vec_t dist, bestdist;
2245 msurface_t *surface;
2247 PRVM_G_FLOAT(OFS_RETURN) = -1;
2248 ed = PRVM_G_EDICT(OFS_PARM0);
2249 point = PRVM_G_VECTOR(OFS_PARM1);
2251 if (!ed || ed->priv.server->free)
2253 model = getmodel(ed);
2254 if (!model || !model->num_surfaces)
2257 // FIXME: implement rotation/scaling
2258 VectorSubtract(point, ed->fields.server->origin, p);
2260 bestdist = 1000000000;
2261 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2263 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2264 // first see if the nearest point on the surface's box is closer than the previous match
2265 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2266 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2267 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2268 dist = VectorLength2(clipped);
2269 if (dist < bestdist)
2271 // it is, check the nearest point on the actual geometry
2272 clippointtosurface(model, surface, p, clipped);
2273 VectorSubtract(clipped, p, clipped);
2274 dist += VectorLength2(clipped);
2275 if (dist < bestdist)
2277 // that's closer too, store it as the best match
2283 PRVM_G_FLOAT(OFS_RETURN) = best;
2285 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2286 void PF_getsurfaceclippedpoint(void)
2290 msurface_t *surface;
2292 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2293 ed = PRVM_G_EDICT(OFS_PARM0);
2294 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2296 // FIXME: implement rotation/scaling
2297 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2298 clippointtosurface(model, surface, p, out);
2299 // FIXME: implement rotation/scaling
2300 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2303 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2304 //this function originally written by KrimZon, made shorter by LordHavoc
2305 void PF_clientcommand (void)
2307 client_t *temp_client;
2310 //find client for this entity
2311 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2312 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2314 Con_Print("PF_clientcommand: entity is not a client\n");
2318 temp_client = host_client;
2319 host_client = svs.clients + i;
2320 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2321 host_client = temp_client;
2324 //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)
2325 void PF_setattachment (void)
2327 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2328 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2329 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2334 if (e == prog->edicts)
2336 VM_Warning("setattachment: can not modify world entity\n");
2339 if (e->priv.server->free)
2341 VM_Warning("setattachment: can not modify free entity\n");
2345 if (tagentity == NULL)
2346 tagentity = prog->edicts;
2348 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2350 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2352 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2355 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2357 modelindex = (int)tagentity->fields.server->modelindex;
2358 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2360 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2362 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);
2365 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));
2369 /////////////////////////////////////////
2370 // DP_MD3_TAGINFO extension coded by VorteX
2372 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2377 i = (int)e->fields.server->modelindex;
2378 if (i < 1 || i >= MAX_MODELS)
2380 model = sv.models[i];
2382 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2385 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2387 float scale = PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float;
2391 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);
2393 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);
2396 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2402 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2403 && (model = sv.models[(int)ent->fields.server->modelindex])
2404 && model->animscenes)
2406 // if model has wrong frame, engine automatically switches to model first frame
2407 frame = (int)ent->fields.server->frame;
2408 if (frame < 0 || frame >= model->numframes)
2410 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2412 *out = identitymatrix;
2416 // Warnings/errors code:
2417 // 0 - normal (everything all-right)
2420 // 3 - null or non-precached model
2421 // 4 - no tags with requested index
2422 // 5 - runaway loop at attachment chain
2423 extern cvar_t cl_bob;
2424 extern cvar_t cl_bobcycle;
2425 extern cvar_t cl_bobup;
2426 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2430 int modelindex, attachloop;
2431 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2434 *out = identitymatrix; // warnings and errors return identical matrix
2436 if (ent == prog->edicts)
2438 if (ent->priv.server->free)
2441 modelindex = (int)ent->fields.server->modelindex;
2442 if (modelindex <= 0 || modelindex > MAX_MODELS)
2445 model = sv.models[modelindex];
2447 tagmatrix = identitymatrix;
2448 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2452 if (attachloop >= 256) // prevent runaway looping
2454 // apply transformation by child's tagindex on parent entity and then
2455 // by parent entity itself
2456 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2457 if (ret && attachloop == 0)
2459 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2460 SV_GetEntityMatrix(ent, &entitymatrix, false);
2461 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2462 // next iteration we process the parent entity
2463 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2465 tagindex = (int)PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
2466 ent = PRVM_EDICT_NUM(val->edict);
2473 // RENDER_VIEWMODEL magic
2474 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2476 Matrix4x4_Copy(&tagmatrix, out);
2477 ent = PRVM_EDICT_NUM(val->edict);
2479 SV_GetEntityMatrix(ent, &entitymatrix, true);
2480 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2483 // Cl_bob, ported from rendering code
2484 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2487 // LordHavoc: this code is *weird*, but not replacable (I think it
2488 // should be done in QC on the server, but oh well, quake is quake)
2489 // LordHavoc: figured out bobup: the time at which the sin is at 180
2490 // degrees (which allows lengthening or squishing the peak or valley)
2491 cycle = sv.time/cl_bobcycle.value;
2492 cycle -= (int)cycle;
2493 if (cycle < cl_bobup.value)
2494 cycle = sin(M_PI * cycle / cl_bobup.value);
2496 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2497 // bob is proportional to velocity in the xy plane
2498 // (don't count Z, or jumping messes it up)
2499 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;
2500 bob = bob*0.3 + bob*0.7*cycle;
2501 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2508 //float(entity ent, string tagname) gettagindex;
2510 void PF_gettagindex (void)
2512 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2513 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2514 int modelindex, tag_index;
2516 if (ent == prog->edicts)
2518 VM_Warning("gettagindex: can't affect world entity\n");
2521 if (ent->priv.server->free)
2523 VM_Warning("gettagindex: can't affect free entity\n");
2527 modelindex = (int)ent->fields.server->modelindex;
2529 if (modelindex <= 0 || modelindex > MAX_MODELS)
2530 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2533 tag_index = SV_GetTagIndex(ent, tag_name);
2535 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2537 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2540 //vector(entity ent, float tagindex) gettaginfo;
2541 void PF_gettaginfo (void)
2543 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2544 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2545 matrix4x4_t tag_matrix;
2548 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2549 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2554 VM_Warning("gettagindex: can't affect world entity\n");
2557 VM_Warning("gettagindex: can't affect free entity\n");
2560 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2563 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2566 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2571 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2572 void PF_dropclient (void)
2575 client_t *oldhostclient;
2576 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2577 if (clientnum < 0 || clientnum >= svs.maxclients)
2579 VM_Warning("dropclient: not a client\n");
2582 if (!svs.clients[clientnum].active)
2584 VM_Warning("dropclient: that client slot is not connected\n");
2587 oldhostclient = host_client;
2588 host_client = svs.clients + clientnum;
2589 SV_DropClient(false);
2590 host_client = oldhostclient;
2593 //entity() spawnclient (DP_SV_BOTCLIENT)
2594 void PF_spawnclient (void)
2598 prog->xfunction->builtinsprofile += 2;
2600 for (i = 0;i < svs.maxclients;i++)
2602 if (!svs.clients[i].active)
2604 prog->xfunction->builtinsprofile += 100;
2605 SV_ConnectClient (i, NULL);
2606 // this has to be set or else ClientDisconnect won't be called
2607 // we assume the qc will call ClientConnect...
2608 svs.clients[i].clientconnectcalled = true;
2609 ed = PRVM_EDICT_NUM(i + 1);
2613 VM_RETURN_EDICT(ed);
2616 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2617 void PF_clienttype (void)
2620 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2621 if (clientnum < 0 || clientnum >= svs.maxclients)
2622 PRVM_G_FLOAT(OFS_RETURN) = 3;
2623 else if (!svs.clients[clientnum].active)
2624 PRVM_G_FLOAT(OFS_RETURN) = 0;
2625 else if (svs.clients[clientnum].netconnection)
2626 PRVM_G_FLOAT(OFS_RETURN) = 1;
2628 PRVM_G_FLOAT(OFS_RETURN) = 2;
2631 void PF_edict_num (void)
2633 VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0)));
2636 prvm_builtin_t vm_sv_builtins[] = {
2638 PF_makevectors, // #1 void(vector ang) makevectors
2639 PF_setorigin, // #2 void(entity e, vector o) setorigin
2640 PF_setmodel, // #3 void(entity e, string m) setmodel
2641 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2642 NULL, // #5 void(entity e, vector min, vector max) setabssize
2643 VM_break, // #6 void() break
2644 VM_random, // #7 float() random
2645 PF_sound, // #8 void(entity e, float chan, string samp) sound
2646 VM_normalize, // #9 vector(vector v) normalize
2647 VM_error, // #10 void(string e) error
2648 VM_objerror, // #11 void(string e) objerror
2649 VM_vlen, // #12 float(vector v) vlen
2650 VM_vectoyaw, // #13 float(vector v) vectoyaw
2651 VM_spawn, // #14 entity() spawn
2652 VM_remove, // #15 void(entity e) remove
2653 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2654 PF_checkclient, // #17 entity() clientlist
2655 VM_find, // #18 entity(entity start, .string fld, string match) find
2656 PF_precache_sound, // #19 void(string s) precache_sound
2657 PF_precache_model, // #20 void(string s) precache_model
2658 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2659 PF_findradius, // #22 entity(vector org, float rad) findradius
2660 VM_bprint, // #23 void(string s) bprint
2661 PF_sprint, // #24 void(entity client, string s) sprint
2662 VM_dprint, // #25 void(string s) dprint
2663 VM_ftos, // #26 void(string s) ftos
2664 VM_vtos, // #27 void(string s) vtos
2665 VM_coredump, // #28 void() coredump
2666 VM_traceon, // #29 void() traceon
2667 VM_traceoff, // #30 void() traceoff
2668 VM_eprint, // #31 void(entity e) eprint
2669 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2671 PF_droptofloor, // #34 float() droptofloor
2672 PF_lightstyle, // #35 void(float style, string value) lightstyle
2673 VM_rint, // #36 float(float v) rint
2674 VM_floor, // #37 float(float v) floor
2675 VM_ceil, // #38 float(float v) ceil
2677 PF_checkbottom, // #40 float(entity e) checkbottom
2678 PF_pointcontents, // #41 float(vector v) pointcontents
2680 VM_fabs, // #43 float(float f) fabs
2681 PF_aim, // #44 vector(entity e, float speed) aim
2682 VM_cvar, // #45 float(string s) cvar
2683 VM_localcmd, // #46 void(string s) localcmd
2684 VM_nextent, // #47 entity(entity e) nextent
2685 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2686 PF_changeyaw, // #49 void() ChangeYaw
2688 VM_vectoangles, // #51 vector(vector v) vectoangles
2689 PF_WriteByte, // #52 void(float to, float f) WriteByte
2690 PF_WriteChar, // #53 void(float to, float f) WriteChar
2691 PF_WriteShort, // #54 void(float to, float f) WriteShort
2692 PF_WriteLong, // #55 void(float to, float f) WriteLong
2693 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2694 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2695 PF_WriteString, // #58 void(float to, string s) WriteString
2696 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2697 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2698 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2699 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2700 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2701 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2702 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2704 SV_MoveToGoal, // #67 void(float step) movetogoal
2705 PF_precache_file, // #68 string(string s) precache_file
2706 PF_makestatic, // #69 void(entity e) makestatic
2707 VM_changelevel, // #70 void(string s) changelevel
2709 VM_cvar_set, // #72 void(string var, string val) cvar_set
2710 PF_centerprint, // #73 void(entity client, strings) centerprint
2711 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2712 PF_precache_model, // #75 string(string s) precache_model2
2713 PF_precache_sound, // #76 string(string s) precache_sound2
2714 PF_precache_file, // #77 string(string s) precache_file2
2715 PF_setspawnparms, // #78 void(entity e) setspawnparms
2718 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2727 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2728 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2729 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2730 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2731 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2732 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2733 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2734 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2735 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2736 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2747 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2748 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2749 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2750 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2751 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2752 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2753 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2754 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2755 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2756 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2757 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2758 // FTEQW range #200-#299
2777 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2787 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2788 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2789 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2790 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2791 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2792 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2793 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2794 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2795 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2796 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2797 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2798 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2799 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2800 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2801 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2802 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2803 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2804 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2805 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2806 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2807 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2808 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2809 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2810 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2811 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2812 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2813 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2814 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2815 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2816 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2817 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2818 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2819 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2820 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2821 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2822 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2823 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2824 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2825 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2826 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2827 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2828 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2829 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2830 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2831 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2832 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2833 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2834 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2835 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2836 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2837 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2838 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2839 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2840 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2841 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2842 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2843 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2844 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2845 PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2847 PF_edict_num, // #459 entity(float num) (??)
2848 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2849 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2850 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2851 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2852 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2853 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2854 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2855 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2856 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2857 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2858 PF_SV_AddStat, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2859 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
2860 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
2861 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
2862 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
2863 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
2864 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
2865 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
2868 e10, e10 // #480-499 (LordHavoc)
2871 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2873 void VM_SV_Cmd_Init(void)
2878 void VM_SV_Cmd_Reset(void)