6 //============================================================================
11 const char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
24 "DP_CSQC_ENTITYNOCULL "
25 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
26 "DP_CSQC_MULTIFRAME_INTERPOLATION "
27 "DP_CSQC_BOXPARTICLES "
28 "DP_CSQC_SPAWNPARTICLE "
29 "DP_CSQC_QUERYRENDERENTITY "
30 "DP_CSQC_ROTATEMOVES "
43 "DP_EF_RESTARTANIM_BIT "
48 "DP_ENT_CUSTOMCOLORMAP "
49 "DP_ENT_EXTERIORMODELTOCLIENT "
52 "DP_ENT_LOWPRECISION "
54 "DP_ENT_TRAILEFFECTNUM "
57 "DP_GFX_EXTERNALTEXTURES "
58 "DP_GFX_EXTERNALTEXTURES_PERMAP "
60 "DP_GFX_MODEL_INTERPOLATION "
61 "DP_GFX_QUAKE3MODELTAGS "
65 "DP_GFX_FONTS_FREETYPE "
67 "DP_FONT_VARIABLEWIDTH "
69 "DP_HALFLIFE_MAP_CVAR "
72 "DP_LIGHTSTYLE_STATICVALUE "
76 "DP_MOVETYPEBOUNCEMISSILE "
79 "DP_QC_ASINACOSATANATAN2TAN "
85 "DP_QC_CVAR_DEFSTRING "
86 "DP_QC_CVAR_DESCRIPTION "
93 "DP_QC_EXTRESPONSEPACKET "
95 "DP_QC_FINDCHAINFLAGS "
96 "DP_QC_FINDCHAINFLOAT "
97 "DP_QC_FINDCHAIN_TOFIELD "
103 "DP_QC_GETSURFACETRIANGLE "
104 "DP_QC_GETSURFACEPOINTATTRIBUTE "
106 "DP_QC_GETTAGINFO_BONEPROPERTIES "
108 "DP_QC_GETTIME_CDTRACK "
111 "DP_QC_MULTIPLETEMPSTRINGS "
112 "DP_QC_NUM_FOR_EDICT "
114 "DP_QC_SINCOSSQRTPOW "
117 "DP_QC_STRINGBUFFERS "
118 "DP_QC_STRINGBUFFERS_CVARLIST "
119 "DP_QC_STRINGCOLORFUNCTIONS "
120 "DP_QC_STRING_CASE_FUNCTIONS "
122 "DP_QC_TOKENIZEBYSEPARATOR "
123 "DP_QC_TOKENIZE_CONSOLE "
126 "DP_QC_TRACE_MOVETYPE_HITMODEL "
127 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
128 "DP_QC_UNLIMITEDTEMPSTRINGS "
132 "DP_QC_VECTOANGLES_WITH_ROLL "
133 "DP_QC_VECTORVECTORS "
140 "DP_SKELETONOBJECTS "
141 "DP_SND_DIRECTIONLESSATTNNONE "
143 "DP_SND_SOUND7_WIP1 "
147 "DP_SND_GETSOUNDTIME "
149 "DP_VIDEO_SUBTITLES "
153 "DP_SV_BOUNCEFACTOR "
154 "DP_SV_CLIENTCAMERA "
155 "DP_SV_CLIENTCOLORS "
158 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
159 "DP_SV_DISCARDABLEDEMO "
160 "DP_SV_DRAWONLYTOCLIENT "
163 "DP_SV_ENTITYCONTENTSTRANSITION "
164 "DP_SV_MODELFLAGS_AS_EFFECTS "
165 "DP_SV_MOVETYPESTEP_LANDEVENT "
167 "DP_SV_NODRAWTOCLIENT "
168 "DP_SV_ONENTITYNOSPAWNFUNCTION "
169 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
171 "DP_SV_PING_PACKETLOSS "
172 "DP_SV_PLAYERPHYSICS "
174 "DP_SV_POINTPARTICLES "
176 "DP_SV_PRECACHEANYTIME "
180 "DP_SV_ROTATINGBMODEL "
184 "DP_SV_SPAWNFUNC_PREFIX "
185 "DP_SV_WRITEPICTURE "
186 "DP_SV_WRITEUNTERMINATEDSTRING "
190 "DP_TE_EXPLOSIONRGB "
192 "DP_TE_PARTICLECUBE "
193 "DP_TE_PARTICLERAIN "
194 "DP_TE_PARTICLESNOW "
196 "DP_TE_QUADEFFECTS1 "
199 "DP_TE_STANDARDEFFECTBUILTINS "
200 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
204 "FTE_CSQC_SKELETONOBJECTS "
207 "KRIMZON_SV_PARSECLIENTCOMMAND "
210 "NEXUIZ_PLAYERMODEL "
212 "PRYDON_CLIENTCURSOR "
213 "TENEBRAE_GFX_DLIGHTS "
216 //"EXT_CSQC " // not ready yet
223 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.
225 setorigin (entity, origin)
228 static void VM_SV_setorigin (void)
233 VM_SAFEPARMCOUNT(2, VM_setorigin);
235 e = PRVM_G_EDICT(OFS_PARM0);
236 if (e == prog->edicts)
238 VM_Warning("setorigin: can not modify world entity\n");
241 if (e->priv.server->free)
243 VM_Warning("setorigin: can not modify free entity\n");
246 org = PRVM_G_VECTOR(OFS_PARM1);
247 VectorCopy (org, PRVM_serveredictvector(e, origin));
251 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
252 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
256 for (i=0 ; i<3 ; i++)
258 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
260 // set derived values
261 VectorCopy (min, PRVM_serveredictvector(e, mins));
262 VectorCopy (max, PRVM_serveredictvector(e, maxs));
263 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
272 the size box is rotated by the current angle
273 LordHavoc: no it isn't...
275 setsize (entity, minvector, maxvector)
278 static void VM_SV_setsize (void)
283 VM_SAFEPARMCOUNT(3, VM_setsize);
285 e = PRVM_G_EDICT(OFS_PARM0);
286 if (e == prog->edicts)
288 VM_Warning("setsize: can not modify world entity\n");
291 if (e->priv.server->free)
293 VM_Warning("setsize: can not modify free entity\n");
296 min = PRVM_G_VECTOR(OFS_PARM1);
297 max = PRVM_G_VECTOR(OFS_PARM2);
298 SetMinMaxSize (e, min, max, false);
306 setmodel(entity, model)
309 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
310 static void VM_SV_setmodel (void)
316 VM_SAFEPARMCOUNT(2, VM_setmodel);
318 e = PRVM_G_EDICT(OFS_PARM0);
319 if (e == prog->edicts)
321 VM_Warning("setmodel: can not modify world entity\n");
324 if (e->priv.server->free)
326 VM_Warning("setmodel: can not modify free entity\n");
329 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
330 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
331 PRVM_serveredictfloat(e, modelindex) = i;
333 mod = SV_GetModelByIndex(i);
337 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
338 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
340 SetMinMaxSize (e, quakemins, quakemaxs, true);
343 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
350 single print to a specific client
352 sprint(clientent, value)
355 static void VM_SV_sprint (void)
359 char string[VM_STRINGTEMP_LENGTH];
361 VM_VarString(1, string, sizeof(string));
363 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
365 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
366 // LordHavoc: div0 requested that sprintto world operate like print
373 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
375 VM_Warning("tried to centerprint to a non-client\n");
379 client = svs.clients + entnum-1;
380 if (!client->netconnection)
383 MSG_WriteChar(&client->netconnection->message,svc_print);
384 MSG_WriteString(&client->netconnection->message, string);
392 single print to a specific client
394 centerprint(clientent, value)
397 static void VM_SV_centerprint (void)
401 char string[VM_STRINGTEMP_LENGTH];
403 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
405 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
407 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
409 VM_Warning("tried to centerprint to a non-client\n");
413 client = svs.clients + entnum-1;
414 if (!client->netconnection)
417 VM_VarString(1, string, sizeof(string));
418 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
419 MSG_WriteString(&client->netconnection->message, string);
426 particle(origin, color, count)
429 static void VM_SV_particle (void)
435 VM_SAFEPARMCOUNT(4, VM_SV_particle);
437 org = PRVM_G_VECTOR(OFS_PARM0);
438 dir = PRVM_G_VECTOR(OFS_PARM1);
439 color = PRVM_G_FLOAT(OFS_PARM2);
440 count = PRVM_G_FLOAT(OFS_PARM3);
441 SV_StartParticle (org, dir, (int)color, (int)count);
451 static void VM_SV_ambientsound (void)
455 float vol, attenuation;
458 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
460 pos = PRVM_G_VECTOR (OFS_PARM0);
461 samp = PRVM_G_STRING(OFS_PARM1);
462 vol = PRVM_G_FLOAT(OFS_PARM2);
463 attenuation = PRVM_G_FLOAT(OFS_PARM3);
465 // check to see if samp was properly precached
466 soundnum = SV_SoundIndex(samp, 1);
474 // add an svc_spawnambient command to the level signon packet
477 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
479 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
481 MSG_WriteVector(&sv.signon, pos, sv.protocol);
483 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
484 MSG_WriteShort (&sv.signon, soundnum);
486 MSG_WriteByte (&sv.signon, soundnum);
488 MSG_WriteByte (&sv.signon, (int)(vol*255));
489 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
497 Each entity can have eight independant sound sources, like voice,
500 Channel 0 is an auto-allocate channel, the others override anything
501 already running on that entity/channel pair.
503 An attenuation of 0 will play full volume everywhere in the level.
504 Larger attenuations will drop off.
508 static void VM_SV_sound (void)
512 prvm_edict_t *entity;
518 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
520 entity = PRVM_G_EDICT(OFS_PARM0);
521 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
522 sample = PRVM_G_STRING(OFS_PARM2);
523 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
526 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
530 attenuation = PRVM_G_FLOAT(OFS_PARM4);
534 pitchchange = PRVM_G_FLOAT(OFS_PARM5);
539 if(channel >= 8 && channel <= 15) // weird QW feature
541 flags |= CHANFLAG_RELIABLE;
546 flags = PRVM_G_FLOAT(OFS_PARM6);
548 if (volume < 0 || volume > 255)
550 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
554 if (attenuation < 0 || attenuation > 4)
556 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
560 channel = CHAN_USER2ENGINE(channel);
562 if (!IS_CHAN(channel))
564 VM_Warning("SV_StartSound: channel must be in range 0-127\n");
568 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE);
575 Follows the same logic as VM_SV_sound, except instead of
576 an entity, an origin for the sound is provided, and channel
577 is omitted (since no entity is being tracked).
581 static void VM_SV_pointsound(void)
588 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
590 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
591 sample = PRVM_G_STRING(OFS_PARM1);
592 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
593 attenuation = PRVM_G_FLOAT(OFS_PARM3);
595 if (volume < 0 || volume > 255)
597 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
601 if (attenuation < 0 || attenuation > 4)
603 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
607 SV_StartPointSound (org, sample, volume, attenuation);
614 Used for use tracing and shot targeting
615 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
616 if the tryents flag is set.
618 traceline (vector1, vector2, movetype, ignore)
621 static void VM_SV_traceline (void)
628 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
630 prog->xfunction->builtinsprofile += 30;
632 v1 = PRVM_G_VECTOR(OFS_PARM0);
633 v2 = PRVM_G_VECTOR(OFS_PARM1);
634 move = (int)PRVM_G_FLOAT(OFS_PARM2);
635 ent = PRVM_G_EDICT(OFS_PARM3);
637 if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
638 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));
640 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
642 VM_SetTraceGlobals(&trace);
650 Used for use tracing and shot targeting
651 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
652 if the tryents flag is set.
654 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
657 // LordHavoc: added this for my own use, VERY useful, similar to traceline
658 static void VM_SV_tracebox (void)
660 float *v1, *v2, *m1, *m2;
665 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
667 prog->xfunction->builtinsprofile += 30;
669 v1 = PRVM_G_VECTOR(OFS_PARM0);
670 m1 = PRVM_G_VECTOR(OFS_PARM1);
671 m2 = PRVM_G_VECTOR(OFS_PARM2);
672 v2 = PRVM_G_VECTOR(OFS_PARM3);
673 move = (int)PRVM_G_FLOAT(OFS_PARM4);
674 ent = PRVM_G_EDICT(OFS_PARM5);
676 if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
677 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));
679 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
681 VM_SetTraceGlobals(&trace);
684 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
689 vec3_t original_origin;
690 vec3_t original_velocity;
691 vec3_t original_angles;
692 vec3_t original_avelocity;
695 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
696 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
697 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
698 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
700 gravity = PRVM_serveredictfloat(tossent, gravity);
703 gravity *= sv_gravity.value * 0.025;
705 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
707 SV_CheckVelocity (tossent);
708 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
709 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
710 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
711 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
712 trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
713 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
714 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
716 if (trace.fraction < 1)
720 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
721 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
722 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
723 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
728 static void VM_SV_tracetoss (void)
732 prvm_edict_t *ignore;
734 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
736 prog->xfunction->builtinsprofile += 600;
738 ent = PRVM_G_EDICT(OFS_PARM0);
739 if (ent == prog->edicts)
741 VM_Warning("tracetoss: can not use world entity\n");
744 ignore = PRVM_G_EDICT(OFS_PARM1);
746 trace = SV_Trace_Toss (ent, ignore);
748 VM_SetTraceGlobals(&trace);
751 //============================================================================
753 static int checkpvsbytes;
754 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
756 static int VM_SV_newcheckclient (int check)
762 // cycle to the next one
764 check = bound(1, check, svs.maxclients);
765 if (check == svs.maxclients)
773 prog->xfunction->builtinsprofile++;
775 if (i == svs.maxclients+1)
777 // look up the client's edict
778 ent = PRVM_EDICT_NUM(i);
779 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
780 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
782 // found a valid client (possibly the same one again)
786 // get the PVS for the entity
787 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
789 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
790 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
799 Returns a client (or object that has a client enemy) that would be a
802 If there is more than one valid option, they are cycled each frame
804 If (self.origin + self.viewofs) is not in the PVS of the current target,
805 it is not returned at all.
810 int c_invis, c_notvis;
811 static void VM_SV_checkclient (void)
813 prvm_edict_t *ent, *self;
816 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
818 // find a new check if on a new frame
819 if (sv.time - sv.lastchecktime >= 0.1)
821 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
822 sv.lastchecktime = sv.time;
825 // return check if it might be visible
826 ent = PRVM_EDICT_NUM(sv.lastcheck);
827 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
829 VM_RETURN_EDICT(prog->edicts);
833 // if current entity can't possibly see the check entity, return 0
834 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
835 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
836 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
839 VM_RETURN_EDICT(prog->edicts);
843 // might be able to see it
845 VM_RETURN_EDICT(ent);
848 //============================================================================
854 Checks if an entity is in a point's PVS.
855 Should be fast but can be inexact.
857 float checkpvs(vector viewpos, entity viewee) = #240;
860 static void VM_SV_checkpvs (void)
863 prvm_edict_t *viewee;
868 unsigned char fatpvs[MAX_MAP_LEAFS/8];
871 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
872 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
873 viewee = PRVM_G_EDICT(OFS_PARM1);
875 if(viewee->priv.server->free)
877 VM_Warning("checkpvs: can not check free entity\n");
878 PRVM_G_FLOAT(OFS_RETURN) = 4;
883 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
885 // no PVS support on this worldmodel... darn
886 PRVM_G_FLOAT(OFS_RETURN) = 3;
889 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
892 // viewpos isn't in any PVS... darn
893 PRVM_G_FLOAT(OFS_RETURN) = 2;
896 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
898 // using fat PVS like FTEQW does (slow)
899 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
901 // no PVS support on this worldmodel... darn
902 PRVM_G_FLOAT(OFS_RETURN) = 3;
905 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
908 // viewpos isn't in any PVS... darn
909 PRVM_G_FLOAT(OFS_RETURN) = 2;
912 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
921 Sends text over to the client's execution buffer
923 stuffcmd (clientent, value, ...)
926 static void VM_SV_stuffcmd (void)
930 char string[VM_STRINGTEMP_LENGTH];
932 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
934 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
935 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
937 VM_Warning("Can't stuffcmd to a non-client\n");
941 VM_VarString(1, string, sizeof(string));
944 host_client = svs.clients + entnum-1;
945 Host_ClientCommands ("%s", string);
953 Returns a chain of entities that have origins within a spherical area
955 findradius (origin, radius)
958 static void VM_SV_findradius (void)
960 prvm_edict_t *ent, *chain;
961 vec_t radius, radius2;
962 vec3_t org, eorg, mins, maxs;
965 static prvm_edict_t *touchedicts[MAX_EDICTS];
968 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
971 chainfield = PRVM_G_INT(OFS_PARM2);
973 chainfield = prog->fieldoffsets.chain;
975 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
977 chain = (prvm_edict_t *)prog->edicts;
979 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
980 radius = PRVM_G_FLOAT(OFS_PARM1);
981 radius2 = radius * radius;
983 mins[0] = org[0] - (radius + 1);
984 mins[1] = org[1] - (radius + 1);
985 mins[2] = org[2] - (radius + 1);
986 maxs[0] = org[0] + (radius + 1);
987 maxs[1] = org[1] + (radius + 1);
988 maxs[2] = org[2] + (radius + 1);
989 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
990 if (numtouchedicts > MAX_EDICTS)
992 // this never happens
993 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
994 numtouchedicts = MAX_EDICTS;
996 for (i = 0;i < numtouchedicts;i++)
998 ent = touchedicts[i];
999 prog->xfunction->builtinsprofile++;
1000 // Quake did not return non-solid entities but darkplaces does
1001 // (note: this is the reason you can't blow up fallen zombies)
1002 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1004 // LordHavoc: compare against bounding box rather than center so it
1005 // doesn't miss large objects, and use DotProduct instead of Length
1006 // for a major speedup
1007 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1008 if (sv_gameplayfix_findradiusdistancetobox.integer)
1010 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1011 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1012 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1015 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1016 if (DotProduct(eorg, eorg) < radius2)
1018 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1023 VM_RETURN_EDICT(chain);
1026 static void VM_SV_precache_sound (void)
1028 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1029 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1032 static void VM_SV_precache_model (void)
1034 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1035 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1036 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1043 float(float yaw, float dist[, settrace]) walkmove
1046 static void VM_SV_walkmove (void)
1055 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1057 // assume failure if it returns early
1058 PRVM_G_FLOAT(OFS_RETURN) = 0;
1060 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1061 if (ent == prog->edicts)
1063 VM_Warning("walkmove: can not modify world entity\n");
1066 if (ent->priv.server->free)
1068 VM_Warning("walkmove: can not modify free entity\n");
1071 yaw = PRVM_G_FLOAT(OFS_PARM0);
1072 dist = PRVM_G_FLOAT(OFS_PARM1);
1073 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1075 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1078 yaw = yaw*M_PI*2 / 360;
1080 move[0] = cos(yaw)*dist;
1081 move[1] = sin(yaw)*dist;
1084 // save program state, because SV_movestep may call other progs
1085 oldf = prog->xfunction;
1086 oldself = PRVM_serverglobaledict(self);
1088 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1091 // restore program state
1092 prog->xfunction = oldf;
1093 PRVM_serverglobaledict(self) = oldself;
1103 static void VM_SV_droptofloor (void)
1109 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1111 // assume failure if it returns early
1112 PRVM_G_FLOAT(OFS_RETURN) = 0;
1114 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1115 if (ent == prog->edicts)
1117 VM_Warning("droptofloor: can not modify world entity\n");
1120 if (ent->priv.server->free)
1122 VM_Warning("droptofloor: can not modify free entity\n");
1126 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1129 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1130 SV_UnstickEntity(ent);
1132 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1133 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1136 VectorSet(offset, 0.5f * (PRVM_serveredictvector(ent, mins)[0] + PRVM_serveredictvector(ent, maxs)[0]), 0.5f * (PRVM_serveredictvector(ent, mins)[1] + PRVM_serveredictvector(ent, maxs)[1]), PRVM_serveredictvector(ent, mins)[2]);
1137 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1138 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1139 VectorSubtract(trace.endpos, offset, trace.endpos);
1140 if (trace.startsolid)
1142 Con_DPrintf("droptofloor at %f %f %f - COULD NOT FIX BADLY PLACED ENTITY\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
1143 SV_UnstickEntity(ent);
1145 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1146 PRVM_serveredictedict(ent, groundentity) = 0;
1147 PRVM_G_FLOAT(OFS_RETURN) = 1;
1149 else if (trace.fraction < 1)
1151 Con_DPrintf("droptofloor at %f %f %f - FIXED BADLY PLACED ENTITY\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
1152 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1153 SV_UnstickEntity(ent);
1155 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1156 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1157 PRVM_G_FLOAT(OFS_RETURN) = 1;
1158 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1159 ent->priv.server->suspendedinairflag = true;
1164 if (trace.fraction != 1)
1166 if (trace.fraction < 1)
1167 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1169 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1170 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1171 PRVM_G_FLOAT(OFS_RETURN) = 1;
1172 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1173 ent->priv.server->suspendedinairflag = true;
1182 void(float style, string value) lightstyle
1185 static void VM_SV_lightstyle (void)
1192 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1194 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1195 val = PRVM_G_STRING(OFS_PARM1);
1197 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1198 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1201 // change the string in sv
1202 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1204 // send message to all clients on this server
1205 if (sv.state != ss_active)
1208 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1210 if (client->active && client->netconnection)
1212 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1213 MSG_WriteChar (&client->netconnection->message,style);
1214 MSG_WriteString (&client->netconnection->message, val);
1224 static void VM_SV_checkbottom (void)
1226 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1227 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1235 static void VM_SV_pointcontents (void)
1237 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1238 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1245 Pick a vector for the player to shoot along
1246 vector aim(entity, missilespeed)
1249 static void VM_SV_aim (void)
1251 prvm_edict_t *ent, *check, *bestent;
1252 vec3_t start, dir, end, bestdir;
1255 float dist, bestdist;
1258 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1260 // assume failure if it returns early
1261 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1262 // if sv_aim is so high it can't possibly accept anything, skip out early
1263 if (sv_aim.value >= 1)
1266 ent = PRVM_G_EDICT(OFS_PARM0);
1267 if (ent == prog->edicts)
1269 VM_Warning("aim: can not use world entity\n");
1272 if (ent->priv.server->free)
1274 VM_Warning("aim: can not use free entity\n");
1277 //speed = PRVM_G_FLOAT(OFS_PARM1);
1279 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1282 // try sending a trace straight
1283 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1284 VectorMA (start, 2048, dir, end);
1285 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1286 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1287 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1289 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1294 // try all possible entities
1295 VectorCopy (dir, bestdir);
1296 bestdist = sv_aim.value;
1299 check = PRVM_NEXT_EDICT(prog->edicts);
1300 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1302 prog->xfunction->builtinsprofile++;
1303 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1307 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1308 continue; // don't aim at teammate
1309 for (j=0 ; j<3 ; j++)
1310 end[j] = PRVM_serveredictvector(check, origin)[j]
1311 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1312 VectorSubtract (end, start, dir);
1313 VectorNormalize (dir);
1314 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1315 if (dist < bestdist)
1316 continue; // to far to turn
1317 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1318 if (tr.ent == check)
1319 { // can shoot at this one
1327 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1328 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1329 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1331 VectorNormalize (end);
1332 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1336 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1341 ===============================================================================
1345 ===============================================================================
1348 #define MSG_BROADCAST 0 // unreliable to all
1349 #define MSG_ONE 1 // reliable to one (msg_entity)
1350 #define MSG_ALL 2 // reliable to all
1351 #define MSG_INIT 3 // write to the init string
1352 #define MSG_ENTITY 5
1354 sizebuf_t *WriteDest (void)
1360 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1364 return &sv.datagram;
1367 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1368 entnum = PRVM_NUM_FOR_EDICT(ent);
1369 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1371 VM_Warning ("WriteDest: tried to write to non-client\n");
1372 return &sv.reliable_datagram;
1375 return &svs.clients[entnum-1].netconnection->message;
1378 VM_Warning ("WriteDest: bad destination\n");
1380 return &sv.reliable_datagram;
1386 return sv.writeentitiestoclient_msg;
1392 static void VM_SV_WriteByte (void)
1394 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1395 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1398 static void VM_SV_WriteChar (void)
1400 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1401 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1404 static void VM_SV_WriteShort (void)
1406 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1407 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1410 static void VM_SV_WriteLong (void)
1412 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1413 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1416 static void VM_SV_WriteAngle (void)
1418 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1419 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1422 static void VM_SV_WriteCoord (void)
1424 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1425 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1428 static void VM_SV_WriteString (void)
1430 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1431 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1434 static void VM_SV_WriteUnterminatedString (void)
1436 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1437 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1441 static void VM_SV_WriteEntity (void)
1443 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1444 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1447 // writes a picture as at most size bytes of data
1449 // IMGNAME \0 SIZE(short) IMGDATA
1450 // if failed to read/compress:
1452 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1453 static void VM_SV_WritePicture (void)
1455 const char *imgname;
1459 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1461 imgname = PRVM_G_STRING(OFS_PARM1);
1462 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1466 MSG_WriteString(WriteDest(), imgname);
1467 if(Image_Compress(imgname, size, &buf, &size))
1470 MSG_WriteShort(WriteDest(), size);
1471 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1476 MSG_WriteShort(WriteDest(), 0);
1480 //////////////////////////////////////////////////////////
1482 static void VM_SV_makestatic (void)
1487 // allow 0 parameters due to an id1 qc bug in which this function is used
1488 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1489 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1491 if (prog->argc >= 1)
1492 ent = PRVM_G_EDICT(OFS_PARM0);
1494 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1495 if (ent == prog->edicts)
1497 VM_Warning("makestatic: can not modify world entity\n");
1500 if (ent->priv.server->free)
1502 VM_Warning("makestatic: can not modify free entity\n");
1507 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1512 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1513 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1514 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1516 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1518 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1519 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1520 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1524 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1525 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1526 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1529 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1530 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1531 for (i=0 ; i<3 ; i++)
1533 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1534 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1537 // throw the entity away now
1541 //=============================================================================
1548 static void VM_SV_setspawnparms (void)
1554 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1556 ent = PRVM_G_EDICT(OFS_PARM0);
1557 i = PRVM_NUM_FOR_EDICT(ent);
1558 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1560 Con_Print("tried to setspawnparms on a non-client\n");
1564 // copy spawn parms out of the client_t
1565 client = svs.clients + i-1;
1566 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1567 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1574 Returns a color vector indicating the lighting at the requested point.
1576 (Internal Operation note: actually measures the light beneath the point, just like
1577 the model lighting on the client)
1582 static void VM_SV_getlight (void)
1584 vec3_t ambientcolor, diffusecolor, diffusenormal;
1586 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1587 p = PRVM_G_VECTOR(OFS_PARM0);
1588 VectorClear(ambientcolor);
1589 VectorClear(diffusecolor);
1590 VectorClear(diffusenormal);
1591 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1592 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1593 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1598 unsigned char type; // 1/2/8 or other value if isn't used
1602 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1603 static int vm_customstats_last;
1605 void VM_CustomStats_Clear (void)
1609 Z_Free(vm_customstats);
1610 vm_customstats = NULL;
1611 vm_customstats_last = -1;
1615 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1623 for(i=0; i<vm_customstats_last+1 ;i++)
1625 if(!vm_customstats[i].type)
1627 switch(vm_customstats[i].type)
1629 //string as 16 bytes
1632 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1633 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1634 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1635 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1636 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1638 //float field sent as-is
1640 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1642 //integer value of float field
1644 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1652 // void(float index, float type, .void field) SV_AddStat = #232;
1653 // Set up an auto-sent player stat.
1654 // Client's get thier own fields sent to them. Index may not be less than 32.
1655 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1656 // 1: string (4 stats carrying a total of 16 charactures)
1657 // 2: float (one stat, float converted to an integer for transportation)
1658 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1659 static void VM_SV_AddStat (void)
1664 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1668 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1671 VM_Warning("PF_SV_AddStat: not enough memory\n");
1675 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1676 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1677 off = PRVM_G_INT (OFS_PARM2);
1682 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1685 if(i >= (MAX_CL_STATS-32))
1687 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1690 if(i > (MAX_CL_STATS-32-4) && type == 1)
1692 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1695 vm_customstats[i].type = type;
1696 vm_customstats[i].fieldoffset = off;
1697 if(vm_customstats_last < i)
1698 vm_customstats_last = i;
1705 copies data from one entity to another
1707 copyentity(src, dst)
1710 static void VM_SV_copyentity (void)
1712 prvm_edict_t *in, *out;
1713 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1714 in = PRVM_G_EDICT(OFS_PARM0);
1715 if (in == prog->edicts)
1717 VM_Warning("copyentity: can not read world entity\n");
1720 if (in->priv.server->free)
1722 VM_Warning("copyentity: can not read free entity\n");
1725 out = PRVM_G_EDICT(OFS_PARM1);
1726 if (out == prog->edicts)
1728 VM_Warning("copyentity: can not modify world entity\n");
1731 if (out->priv.server->free)
1733 VM_Warning("copyentity: can not modify free entity\n");
1736 memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
1745 sets the color of a client and broadcasts the update to all connected clients
1747 setcolor(clientent, value)
1750 static void VM_SV_setcolor (void)
1755 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1756 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1757 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1759 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1761 Con_Print("tried to setcolor a non-client\n");
1765 client = svs.clients + entnum-1;
1768 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1769 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1772 if (client->old_colors != client->colors)
1774 client->old_colors = client->colors;
1775 // send notification to all clients
1776 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1777 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1778 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1786 effect(origin, modelname, startframe, framecount, framerate)
1789 static void VM_SV_effect (void)
1793 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1794 s = PRVM_G_STRING(OFS_PARM1);
1797 VM_Warning("effect: no model specified\n");
1801 i = SV_ModelIndex(s, 1);
1804 VM_Warning("effect: model not precached\n");
1808 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1810 VM_Warning("effect: framecount < 1\n");
1814 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1816 VM_Warning("effect: framerate < 1\n");
1820 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));
1823 static void VM_SV_te_blood (void)
1825 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1826 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1828 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1829 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1831 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1832 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1833 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1835 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1836 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1837 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1839 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1840 SV_FlushBroadcastMessages();
1843 static void VM_SV_te_bloodshower (void)
1845 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1846 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1848 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1849 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1851 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1852 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1853 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1855 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1856 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1857 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1859 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1861 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1862 SV_FlushBroadcastMessages();
1865 static void VM_SV_te_explosionrgb (void)
1867 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1868 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1869 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1873 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1875 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1876 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1877 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1878 SV_FlushBroadcastMessages();
1881 static void VM_SV_te_particlecube (void)
1883 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1884 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1886 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1887 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1889 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1890 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1891 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1893 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1894 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1895 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1901 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1903 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1904 // gravity true/false
1905 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1908 SV_FlushBroadcastMessages();
1911 static void VM_SV_te_particlerain (void)
1913 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1914 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1916 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1917 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1919 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1920 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1921 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1923 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1924 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1925 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1931 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1933 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1934 SV_FlushBroadcastMessages();
1937 static void VM_SV_te_particlesnow (void)
1939 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1940 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1942 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1943 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
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);
1949 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1950 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1953 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1954 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1955 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1957 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1959 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1960 SV_FlushBroadcastMessages();
1963 static void VM_SV_te_spark (void)
1965 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1966 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1968 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1969 MSG_WriteByte(&sv.datagram, TE_SPARK);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1972 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1973 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1975 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1976 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1977 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1979 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1980 SV_FlushBroadcastMessages();
1983 static void VM_SV_te_gunshotquad (void)
1985 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1986 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1987 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1989 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1990 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1991 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1992 SV_FlushBroadcastMessages();
1995 static void VM_SV_te_spikequad (void)
1997 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1998 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1999 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2001 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2002 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2004 SV_FlushBroadcastMessages();
2007 static void VM_SV_te_superspikequad (void)
2009 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2010 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2011 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2014 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2015 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2016 SV_FlushBroadcastMessages();
2019 static void VM_SV_te_explosionquad (void)
2021 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2022 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2023 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
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);
2028 SV_FlushBroadcastMessages();
2031 static void VM_SV_te_smallflash (void)
2033 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2034 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2035 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2037 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2038 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2039 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2040 SV_FlushBroadcastMessages();
2043 static void VM_SV_te_customflash (void)
2045 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2046 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2048 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2049 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2052 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2055 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2057 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2059 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2060 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2061 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2062 SV_FlushBroadcastMessages();
2065 static void VM_SV_te_gunshot (void)
2067 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2068 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2069 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2071 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2072 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2074 SV_FlushBroadcastMessages();
2077 static void VM_SV_te_spike (void)
2079 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2080 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2081 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2083 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2084 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2085 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2086 SV_FlushBroadcastMessages();
2089 static void VM_SV_te_superspike (void)
2091 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2092 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2093 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2095 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2096 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2097 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2098 SV_FlushBroadcastMessages();
2101 static void VM_SV_te_explosion (void)
2103 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2104 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2105 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2107 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2108 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2109 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2110 SV_FlushBroadcastMessages();
2113 static void VM_SV_te_tarexplosion (void)
2115 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2116 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2117 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2119 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2120 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2121 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2122 SV_FlushBroadcastMessages();
2125 static void VM_SV_te_wizspike (void)
2127 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2128 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2129 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2131 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2132 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2133 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2134 SV_FlushBroadcastMessages();
2137 static void VM_SV_te_knightspike (void)
2139 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2140 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2141 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2143 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2144 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2145 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2146 SV_FlushBroadcastMessages();
2149 static void VM_SV_te_lavasplash (void)
2151 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2152 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2153 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2155 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2156 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2157 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2158 SV_FlushBroadcastMessages();
2161 static void VM_SV_te_teleport (void)
2163 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2164 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2165 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2167 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2168 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2169 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2170 SV_FlushBroadcastMessages();
2173 static void VM_SV_te_explosion2 (void)
2175 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2176 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2177 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2179 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2180 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2181 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2183 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2184 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2185 SV_FlushBroadcastMessages();
2188 static void VM_SV_te_lightning1 (void)
2190 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2191 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2192 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2194 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2196 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2197 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2198 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2200 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2201 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2202 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2203 SV_FlushBroadcastMessages();
2206 static void VM_SV_te_lightning2 (void)
2208 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2209 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2210 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2212 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2214 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2215 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2216 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2218 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2219 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2220 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2221 SV_FlushBroadcastMessages();
2224 static void VM_SV_te_lightning3 (void)
2226 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2227 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2228 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2230 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2232 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2234 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2236 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2237 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2238 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2239 SV_FlushBroadcastMessages();
2242 static void VM_SV_te_beam (void)
2244 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2245 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2246 MSG_WriteByte(&sv.datagram, TE_BEAM);
2248 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2250 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2251 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2252 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2254 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2255 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2256 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2257 SV_FlushBroadcastMessages();
2260 static void VM_SV_te_plasmaburn (void)
2262 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2263 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2264 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2265 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2266 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2267 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2268 SV_FlushBroadcastMessages();
2271 static void VM_SV_te_flamejet (void)
2273 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2274 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2275 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2277 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2278 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2279 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2281 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2282 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2283 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2285 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2286 SV_FlushBroadcastMessages();
2289 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2290 //this function originally written by KrimZon, made shorter by LordHavoc
2291 static void VM_SV_clientcommand (void)
2293 client_t *temp_client;
2295 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2297 //find client for this entity
2298 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2299 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2301 Con_Print("PF_clientcommand: entity is not a client\n");
2305 temp_client = host_client;
2306 host_client = svs.clients + i;
2307 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2308 host_client = temp_client;
2311 //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)
2312 static void VM_SV_setattachment (void)
2314 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2315 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2316 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2319 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2321 if (e == prog->edicts)
2323 VM_Warning("setattachment: can not modify world entity\n");
2326 if (e->priv.server->free)
2328 VM_Warning("setattachment: can not modify free entity\n");
2332 if (tagentity == NULL)
2333 tagentity = prog->edicts;
2337 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2339 model = SV_GetModelFromEdict(tagentity);
2342 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2344 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);
2347 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));
2350 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2351 PRVM_serveredictfloat(e, tag_index) = tagindex;
2354 /////////////////////////////////////////
2355 // DP_MD3_TAGINFO extension coded by VorteX
2357 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2361 i = (int)PRVM_serveredictfloat(e, modelindex);
2362 if (i < 1 || i >= MAX_MODELS)
2365 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2368 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2375 Matrix4x4_CreateIdentity(tag_localmatrix);
2377 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2379 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2390 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2393 float pitchsign = 1;
2395 scale = PRVM_serveredictfloat(ent, scale);
2400 Matrix4x4_CreateFromQuakeEntity(out, PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2] + PRVM_serveredictvector(ent, view_ofs)[2], PRVM_serveredictvector(ent, v_angle)[0], PRVM_serveredictvector(ent, v_angle)[1], PRVM_serveredictvector(ent, v_angle)[2], scale * cl_viewmodel_scale.value);
2403 pitchsign = SV_GetPitchSign(ent);
2404 Matrix4x4_CreateFromQuakeEntity(out, PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2], pitchsign * PRVM_serveredictvector(ent, angles)[0], PRVM_serveredictvector(ent, angles)[1], PRVM_serveredictvector(ent, angles)[2], scale);
2408 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2411 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2413 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2414 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2415 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2416 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2418 *out = identitymatrix;
2422 // Warnings/errors code:
2423 // 0 - normal (everything all-right)
2426 // 3 - null or non-precached model
2427 // 4 - no tags with requested index
2428 // 5 - runaway loop at attachment chain
2429 extern cvar_t cl_bob;
2430 extern cvar_t cl_bobcycle;
2431 extern cvar_t cl_bobup;
2432 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2435 int modelindex, attachloop;
2436 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2439 *out = identitymatrix; // warnings and errors return identical matrix
2441 if (ent == prog->edicts)
2443 if (ent->priv.server->free)
2446 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2447 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2450 model = SV_GetModelByIndex(modelindex);
2452 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2453 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2454 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2456 tagmatrix = identitymatrix;
2457 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2461 if (attachloop >= 256) // prevent runaway looping
2463 // apply transformation by child's tagindex on parent entity and then
2464 // by parent entity itself
2465 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2466 if (ret && attachloop == 0)
2468 SV_GetEntityMatrix(ent, &entitymatrix, false);
2469 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2470 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2471 // next iteration we process the parent entity
2472 if (PRVM_serveredictedict(ent, tag_entity))
2474 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2475 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2482 // RENDER_VIEWMODEL magic
2483 if (PRVM_serveredictedict(ent, viewmodelforclient))
2485 Matrix4x4_Copy(&tagmatrix, out);
2486 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2488 SV_GetEntityMatrix(ent, &entitymatrix, true);
2489 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2492 // Cl_bob, ported from rendering code
2493 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2496 // LordHavoc: this code is *weird*, but not replacable (I think it
2497 // should be done in QC on the server, but oh well, quake is quake)
2498 // LordHavoc: figured out bobup: the time at which the sin is at 180
2499 // degrees (which allows lengthening or squishing the peak or valley)
2500 cycle = sv.time/cl_bobcycle.value;
2501 cycle -= (int)cycle;
2502 if (cycle < cl_bobup.value)
2503 cycle = sin(M_PI * cycle / cl_bobup.value);
2505 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2506 // bob is proportional to velocity in the xy plane
2507 // (don't count Z, or jumping messes it up)
2508 bob = sqrt(PRVM_serveredictvector(ent, velocity)[0]*PRVM_serveredictvector(ent, velocity)[0] + PRVM_serveredictvector(ent, velocity)[1]*PRVM_serveredictvector(ent, velocity)[1])*cl_bob.value;
2509 bob = bob*0.3 + bob*0.7*cycle;
2510 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2517 //float(entity ent, string tagname) gettagindex;
2519 static void VM_SV_gettagindex (void)
2522 const char *tag_name;
2525 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2527 ent = PRVM_G_EDICT(OFS_PARM0);
2528 tag_name = PRVM_G_STRING(OFS_PARM1);
2530 if (ent == prog->edicts)
2532 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2535 if (ent->priv.server->free)
2537 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2542 if (!SV_GetModelFromEdict(ent))
2543 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2546 tag_index = SV_GetTagIndex(ent, tag_name);
2548 if(developer_extra.integer)
2549 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2551 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2554 //vector(entity ent, float tagindex) gettaginfo;
2555 static void VM_SV_gettaginfo (void)
2559 matrix4x4_t tag_matrix;
2560 matrix4x4_t tag_localmatrix;
2562 const char *tagname;
2564 vec3_t fo, le, up, trans;
2565 const dp_model_t *model;
2567 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2569 e = PRVM_G_EDICT(OFS_PARM0);
2570 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2572 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2573 Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
2574 VectorScale(le, -1, PRVM_serverglobalvector(v_right));
2575 model = SV_GetModelFromEdict(e);
2576 VM_GenerateFrameGroupBlend(e->priv.server->framegroupblend, e);
2577 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
2578 VM_UpdateEdictSkeleton(e, model, e->priv.server->frameblend);
2579 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2580 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2582 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2583 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(tagname) : 0;
2584 VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
2585 VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
2586 VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
2587 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2592 VM_Warning("gettagindex: can't affect world entity\n");
2595 VM_Warning("gettagindex: can't affect free entity\n");
2598 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2601 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2604 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2609 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2610 static void VM_SV_dropclient (void)
2613 client_t *oldhostclient;
2614 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2615 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2616 if (clientnum < 0 || clientnum >= svs.maxclients)
2618 VM_Warning("dropclient: not a client\n");
2621 if (!svs.clients[clientnum].active)
2623 VM_Warning("dropclient: that client slot is not connected\n");
2626 oldhostclient = host_client;
2627 host_client = svs.clients + clientnum;
2628 SV_DropClient(false);
2629 host_client = oldhostclient;
2632 //entity() spawnclient (DP_SV_BOTCLIENT)
2633 static void VM_SV_spawnclient (void)
2637 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2638 prog->xfunction->builtinsprofile += 2;
2640 for (i = 0;i < svs.maxclients;i++)
2642 if (!svs.clients[i].active)
2644 prog->xfunction->builtinsprofile += 100;
2645 SV_ConnectClient (i, NULL);
2646 // this has to be set or else ClientDisconnect won't be called
2647 // we assume the qc will call ClientConnect...
2648 svs.clients[i].clientconnectcalled = true;
2649 ed = PRVM_EDICT_NUM(i + 1);
2653 VM_RETURN_EDICT(ed);
2656 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2657 static void VM_SV_clienttype (void)
2660 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2661 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2662 if (clientnum < 0 || clientnum >= svs.maxclients)
2663 PRVM_G_FLOAT(OFS_RETURN) = 3;
2664 else if (!svs.clients[clientnum].active)
2665 PRVM_G_FLOAT(OFS_RETURN) = 0;
2666 else if (svs.clients[clientnum].netconnection)
2667 PRVM_G_FLOAT(OFS_RETURN) = 1;
2669 PRVM_G_FLOAT(OFS_RETURN) = 2;
2676 string(string key) serverkey
2679 void VM_SV_serverkey(void)
2681 char string[VM_STRINGTEMP_LENGTH];
2682 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2683 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2684 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2687 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2688 static void VM_SV_setmodelindex (void)
2693 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2695 e = PRVM_G_EDICT(OFS_PARM0);
2696 if (e == prog->edicts)
2698 VM_Warning("setmodelindex: can not modify world entity\n");
2701 if (e->priv.server->free)
2703 VM_Warning("setmodelindex: can not modify free entity\n");
2706 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2707 if (i <= 0 || i >= MAX_MODELS)
2709 VM_Warning("setmodelindex: invalid modelindex\n");
2712 if (!sv.model_precache[i][0])
2714 VM_Warning("setmodelindex: model not precached\n");
2718 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
2719 PRVM_serveredictfloat(e, modelindex) = i;
2721 mod = SV_GetModelByIndex(i);
2725 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2726 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2728 SetMinMaxSize (e, quakemins, quakemaxs, true);
2731 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2734 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2735 static void VM_SV_modelnameforindex (void)
2738 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2740 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2742 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2743 if (i <= 0 || i >= MAX_MODELS)
2745 VM_Warning("modelnameforindex: invalid modelindex\n");
2748 if (!sv.model_precache[i][0])
2750 VM_Warning("modelnameforindex: model not precached\n");
2754 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2757 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2758 static void VM_SV_particleeffectnum (void)
2761 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2762 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2765 PRVM_G_FLOAT(OFS_RETURN) = i;
2768 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2769 static void VM_SV_trailparticles (void)
2771 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2773 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2776 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2777 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2778 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2779 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2780 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2781 SV_FlushBroadcastMessages();
2784 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2785 static void VM_SV_pointparticles (void)
2787 int effectnum, count;
2789 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2791 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2794 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2795 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2796 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2797 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2798 if (count == 1 && !VectorLength2(vel))
2801 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2802 MSG_WriteShort(&sv.datagram, effectnum);
2803 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2807 // 1+2+12+12+2=29 bytes
2808 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2809 MSG_WriteShort(&sv.datagram, effectnum);
2810 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2811 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2812 MSG_WriteShort(&sv.datagram, count);
2815 SV_FlushBroadcastMessages();
2818 //PF_setpause, // void(float pause) setpause = #531;
2819 static void VM_SV_setpause(void) {
2821 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2822 if (pauseValue != 0) { //pause the game
2824 sv.pausedstart = Sys_DoubleTime();
2825 } else { //disable pause, in case it was enabled
2826 if (sv.paused != 0) {
2831 // send notification to all clients
2832 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2833 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2836 // #263 float(float modlindex) skel_create = #263; // (FTE_CSQC_SKELETONOBJECTS) create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex.
2837 static void VM_SV_skel_create(void)
2839 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2840 dp_model_t *model = SV_GetModelByIndex(modelindex);
2841 skeleton_t *skeleton;
2843 PRVM_G_FLOAT(OFS_RETURN) = 0;
2844 if (!model || !model->num_bones)
2846 for (i = 0;i < MAX_EDICTS;i++)
2847 if (!prog->skeletons[i])
2849 if (i == MAX_EDICTS)
2851 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2852 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2853 skeleton->model = model;
2854 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2855 // initialize to identity matrices
2856 for (i = 0;i < skeleton->model->num_bones;i++)
2857 skeleton->relativetransforms[i] = identitymatrix;
2860 // #264 float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // (FTE_CSQC_SKELETONOBJECTS) blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure
2861 static void VM_SV_skel_build(void)
2863 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2864 skeleton_t *skeleton;
2865 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2866 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2867 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2868 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2869 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2870 dp_model_t *model = SV_GetModelByIndex(modelindex);
2875 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2876 frameblend_t frameblend[MAX_FRAMEBLENDS];
2877 matrix4x4_t blendedmatrix;
2879 PRVM_G_FLOAT(OFS_RETURN) = 0;
2880 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2882 firstbone = max(0, firstbone);
2883 lastbone = min(lastbone, model->num_bones - 1);
2884 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2885 VM_GenerateFrameGroupBlend(framegroupblend, ed);
2886 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
2887 blendfrac = 1.0f - retainfrac;
2888 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2889 frameblend[numblends].lerp *= blendfrac;
2890 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2892 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2893 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2894 for (blendindex = 0;blendindex < numblends;blendindex++)
2896 Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2897 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2899 skeleton->relativetransforms[bonenum] = blendedmatrix;
2901 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2904 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2905 static void VM_SV_skel_get_numbones(void)
2907 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2908 skeleton_t *skeleton;
2909 PRVM_G_FLOAT(OFS_RETURN) = 0;
2910 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2912 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2915 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2916 static void VM_SV_skel_get_bonename(void)
2918 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2919 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2920 skeleton_t *skeleton;
2921 PRVM_G_INT(OFS_RETURN) = 0;
2922 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2924 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2926 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(skeleton->model->data_bones[bonenum].name);
2929 // #267 float(float skel, float bonenum) skel_get_boneparent = #267; // (FTE_CSQC_SKELETONOBJECTS) returns parent num for supplied bonenum, 0 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
2930 static void VM_SV_skel_get_boneparent(void)
2932 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2933 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2934 skeleton_t *skeleton;
2935 PRVM_G_FLOAT(OFS_RETURN) = 0;
2936 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2938 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2940 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2943 // #268 float(float skel, string tagname) skel_find_bone = #268; // (FTE_CSQC_SKELETONOBJECTS) get number of bone with specified name, 0 on failure, tagindex (bonenum+1) on success, same as using gettagindex on the modelindex
2944 static void VM_SV_skel_find_bone(void)
2946 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2947 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2948 skeleton_t *skeleton;
2949 PRVM_G_FLOAT(OFS_RETURN) = 0;
2950 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2952 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2955 // #269 vector(float skel, float bonenum) skel_get_bonerel = #269; // (FTE_CSQC_SKELETONOBJECTS) get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone)
2956 static void VM_SV_skel_get_bonerel(void)
2958 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2959 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2960 skeleton_t *skeleton;
2962 vec3_t forward, left, up, origin;
2963 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2964 VectorClear(PRVM_clientglobalvector(v_forward));
2965 VectorClear(PRVM_clientglobalvector(v_right));
2966 VectorClear(PRVM_clientglobalvector(v_up));
2967 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2969 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2971 matrix = skeleton->relativetransforms[bonenum];
2972 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2973 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2974 VectorNegate(left, PRVM_clientglobalvector(v_right));
2975 VectorCopy(up, PRVM_clientglobalvector(v_up));
2976 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2979 // #270 vector(float skel, float bonenum) skel_get_boneabs = #270; // (FTE_CSQC_SKELETONOBJECTS) get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity)
2980 static void VM_SV_skel_get_boneabs(void)
2982 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2983 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2984 skeleton_t *skeleton;
2987 vec3_t forward, left, up, origin;
2988 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2989 VectorClear(PRVM_clientglobalvector(v_forward));
2990 VectorClear(PRVM_clientglobalvector(v_right));
2991 VectorClear(PRVM_clientglobalvector(v_up));
2992 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2994 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2996 matrix = skeleton->relativetransforms[bonenum];
2997 // convert to absolute
2998 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3001 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3003 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3004 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3005 VectorNegate(left, PRVM_clientglobalvector(v_right));
3006 VectorCopy(up, PRVM_clientglobalvector(v_up));
3007 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3010 // #271 void(float skel, float bonenum, vector org) skel_set_bone = #271; // (FTE_CSQC_SKELETONOBJECTS) set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
3011 static void VM_SV_skel_set_bone(void)
3013 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3014 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3015 vec3_t forward, left, up, origin;
3016 skeleton_t *skeleton;
3018 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3020 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3022 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3023 VectorNegate(PRVM_clientglobalvector(v_right), left);
3024 VectorCopy(PRVM_clientglobalvector(v_up), up);
3025 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3026 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3027 skeleton->relativetransforms[bonenum] = matrix;
3030 // #272 void(float skel, float bonenum, vector org) skel_mul_bone = #272; // (FTE_CSQC_SKELETONOBJECTS) transform bone matrix (relative to its parent) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
3031 static void VM_SV_skel_mul_bone(void)
3033 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3034 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3035 vec3_t forward, left, up, origin;
3036 skeleton_t *skeleton;
3039 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3041 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3043 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3044 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3045 VectorNegate(PRVM_clientglobalvector(v_right), left);
3046 VectorCopy(PRVM_clientglobalvector(v_up), up);
3047 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3048 temp = skeleton->relativetransforms[bonenum];
3049 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3052 // #273 void(float skel, float startbone, float endbone, vector org) skel_mul_bones = #273; // (FTE_CSQC_SKELETONOBJECTS) transform bone matrices (relative to their parents) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bones)
3053 static void VM_SV_skel_mul_bones(void)
3055 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3056 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3057 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3059 vec3_t forward, left, up, origin;
3060 skeleton_t *skeleton;
3063 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3065 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3066 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3067 VectorNegate(PRVM_clientglobalvector(v_right), left);
3068 VectorCopy(PRVM_clientglobalvector(v_up), up);
3069 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3070 firstbone = max(0, firstbone);
3071 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3072 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3074 temp = skeleton->relativetransforms[bonenum];
3075 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3079 // #274 void(float skeldst, float skelsrc, float startbone, float endbone) skel_copybones = #274; // (FTE_CSQC_SKELETONOBJECTS) copy bone matrices (relative to their parents) from one skeleton to another, useful for copying a skeleton to a corpse
3080 static void VM_SV_skel_copybones(void)
3082 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3083 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3084 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3085 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3087 skeleton_t *skeletondst;
3088 skeleton_t *skeletonsrc;
3089 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3091 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3093 firstbone = max(0, firstbone);
3094 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3095 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3096 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3097 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3100 // #275 void(float skel) skel_delete = #275; // (FTE_CSQC_SKELETONOBJECTS) deletes skeleton at the beginning of the next frame (you can add the entity, delete the skeleton, renderscene, and it will still work)
3101 static void VM_SV_skel_delete(void)
3103 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3104 skeleton_t *skeleton;
3105 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3108 prog->skeletons[skeletonindex] = NULL;
3111 // #276 float(float modlindex, string framename) frameforname = #276; // (FTE_CSQC_SKELETONOBJECTS) finds number of a specified frame in the animation, returns -1 if no match found
3112 static void VM_SV_frameforname(void)
3114 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3115 dp_model_t *model = SV_GetModelByIndex(modelindex);
3116 const char *name = PRVM_G_STRING(OFS_PARM1);
3118 PRVM_G_FLOAT(OFS_RETURN) = -1;
3119 if (!model || !model->animscenes)
3121 for (i = 0;i < model->numframes;i++)
3123 if (!strcasecmp(model->animscenes[i].name, name))
3125 PRVM_G_FLOAT(OFS_RETURN) = i;
3131 // #277 float(float modlindex, float framenum) frameduration = #277; // (FTE_CSQC_SKELETONOBJECTS) returns the intended play time (in seconds) of the specified framegroup, if it does not exist the result is 0, if it is a single frame it may be a small value around 0.1 or 0.
3132 static void VM_SV_frameduration(void)
3134 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3135 dp_model_t *model = SV_GetModelByIndex(modelindex);
3136 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3137 PRVM_G_FLOAT(OFS_RETURN) = 0;
3138 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3140 if (model->animscenes[framenum].framerate)
3141 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3145 prvm_builtin_t vm_sv_builtins[] = {
3146 NULL, // #0 NULL function (not callable) (QUAKE)
3147 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3148 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3149 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3150 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3151 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3152 VM_break, // #6 void() break (QUAKE)
3153 VM_random, // #7 float() random (QUAKE)
3154 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3155 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3156 VM_error, // #10 void(string e) error (QUAKE)
3157 VM_objerror, // #11 void(string e) objerror (QUAKE)
3158 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3159 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3160 VM_spawn, // #14 entity() spawn (QUAKE)
3161 VM_remove, // #15 void(entity e) remove (QUAKE)
3162 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3163 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3164 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3165 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3166 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3167 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3168 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3169 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3170 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3171 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3172 VM_ftos, // #26 string(float f) ftos (QUAKE)
3173 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3174 VM_coredump, // #28 void() coredump (QUAKE)
3175 VM_traceon, // #29 void() traceon (QUAKE)
3176 VM_traceoff, // #30 void() traceoff (QUAKE)
3177 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3178 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3179 NULL, // #33 (QUAKE)
3180 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3181 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3182 VM_rint, // #36 float(float v) rint (QUAKE)
3183 VM_floor, // #37 float(float v) floor (QUAKE)
3184 VM_ceil, // #38 float(float v) ceil (QUAKE)
3185 NULL, // #39 (QUAKE)
3186 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3187 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3188 NULL, // #42 (QUAKE)
3189 VM_fabs, // #43 float(float f) fabs (QUAKE)
3190 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3191 VM_cvar, // #45 float(string s) cvar (QUAKE)
3192 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3193 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3194 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3195 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3196 NULL, // #50 (QUAKE)
3197 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3198 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3199 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3200 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3201 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3202 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3203 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3204 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3205 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3206 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3207 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3208 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3209 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3210 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3211 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3212 NULL, // #66 (QUAKE)
3213 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3214 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3215 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3216 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3217 NULL, // #71 (QUAKE)
3218 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3219 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3220 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3221 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3222 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3223 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3224 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3225 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3226 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3227 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3228 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3229 NULL, // #83 (QUAKE)
3230 NULL, // #84 (QUAKE)
3231 NULL, // #85 (QUAKE)
3232 NULL, // #86 (QUAKE)
3233 NULL, // #87 (QUAKE)
3234 NULL, // #88 (QUAKE)
3235 NULL, // #89 (QUAKE)
3236 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3237 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3238 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3239 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3240 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3241 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3242 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3243 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3244 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3245 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3246 // FrikaC and Telejano range #100-#199
3257 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3258 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3259 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3260 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3261 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3262 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3263 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3264 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3265 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3266 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3347 // FTEQW range #200-#299
3366 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3369 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3370 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3371 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3372 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3373 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3374 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3375 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3376 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3377 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3378 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3380 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3388 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3411 VM_SV_skel_create, // #263 float(float modlindex) skel_create = #263; // (DP_SKELETONOBJECTS) create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex.
3412 VM_SV_skel_build, // #264 float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // (DP_SKELETONOBJECTS) blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure
3413 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3414 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3415 VM_SV_skel_get_boneparent, // #267 float(float skel, float bonenum) skel_get_boneparent = #267; // (DP_SKELETONOBJECTS) returns parent num for supplied bonenum, -1 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
3416 VM_SV_skel_find_bone, // #268 float(float skel, string tagname) skel_find_bone = #268; // (DP_SKELETONOBJECTS) get number of bone with specified name, 0 on failure, tagindex (bonenum+1) on success, same as using gettagindex on the modelindex
3417 VM_SV_skel_get_bonerel, // #269 vector(float skel, float bonenum) skel_get_bonerel = #269; // (DP_SKELETONOBJECTS) get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone)
3418 VM_SV_skel_get_boneabs, // #270 vector(float skel, float bonenum) skel_get_boneabs = #270; // (DP_SKELETONOBJECTS) get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity)
3419 VM_SV_skel_set_bone, // #271 void(float skel, float bonenum, vector org) skel_set_bone = #271; // (DP_SKELETONOBJECTS) set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
3420 VM_SV_skel_mul_bone, // #272 void(float skel, float bonenum, vector org) skel_mul_bone = #272; // (DP_SKELETONOBJECTS) transform bone matrix (relative to its parent) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
3421 VM_SV_skel_mul_bones, // #273 void(float skel, float startbone, float endbone, vector org) skel_mul_bones = #273; // (DP_SKELETONOBJECTS) transform bone matrices (relative to their parents) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bones)
3422 VM_SV_skel_copybones, // #274 void(float skeldst, float skelsrc, float startbone, float endbone) skel_copybones = #274; // (DP_SKELETONOBJECTS) copy bone matrices (relative to their parents) from one skeleton to another, useful for copying a skeleton to a corpse
3423 VM_SV_skel_delete, // #275 void(float skel) skel_delete = #275; // (DP_SKELETONOBJECTS) deletes skeleton at the beginning of the next frame (you can add the entity, delete the skeleton, renderscene, and it will still work)
3424 VM_SV_frameforname, // #276 float(float modlindex, string framename) frameforname = #276; // (DP_SKELETONOBJECTS) finds number of a specified frame in the animation, returns -1 if no match found
3425 VM_SV_frameduration, // #277 float(float modlindex, float framenum) frameduration = #277; // (DP_SKELETONOBJECTS) returns the intended play time (in seconds) of the specified framegroup, if it does not exist the result is 0, if it is a single frame it may be a small value around 0.1 or 0.
3448 // CSQC range #300-#399
3449 NULL, // #300 void() clearscene (EXT_CSQC)
3450 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3451 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3452 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3453 NULL, // #304 void() renderscene (EXT_CSQC)
3454 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3455 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3456 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3457 NULL, // #308 void() R_EndPolygon
3459 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3460 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3464 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3465 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3466 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3467 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3468 NULL, // #319 void(string name) freepic (EXT_CSQC)
3469 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3470 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3471 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3472 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3473 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3474 NULL, // #325 void(void) drawresetcliparea
3479 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3480 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3481 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3482 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3483 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3484 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3485 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3486 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3487 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3488 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3489 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3490 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3491 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3492 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3493 NULL, // #344 vector() getmousepos (EXT_CSQC)
3494 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3495 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3496 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3497 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3498 NULL, // #349 float() isdemo (EXT_CSQC)
3499 VM_isserver, // #350 float() isserver (EXT_CSQC)
3500 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3501 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3502 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3503 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3509 NULL, // #360 float() readbyte (EXT_CSQC)
3510 NULL, // #361 float() readchar (EXT_CSQC)
3511 NULL, // #362 float() readshort (EXT_CSQC)
3512 NULL, // #363 float() readlong (EXT_CSQC)
3513 NULL, // #364 float() readcoord (EXT_CSQC)
3514 NULL, // #365 float() readangle (EXT_CSQC)
3515 NULL, // #366 string() readstring (EXT_CSQC)
3516 NULL, // #367 float() readfloat (EXT_CSQC)
3549 // LordHavoc's range #400-#499
3550 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3551 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3552 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3553 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3554 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3555 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3556 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3557 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3558 VM_SV_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3559 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3560 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3561 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3562 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3563 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3564 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3565 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3566 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3567 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3568 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3569 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3570 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3571 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3572 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3573 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3574 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3575 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3576 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3577 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3578 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3579 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3580 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3581 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3582 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3583 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3584 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3585 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3586 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3587 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3588 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3589 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3590 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3591 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3592 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3593 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3594 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3595 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3596 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3597 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3598 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3599 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3600 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3601 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3602 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3603 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3604 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3605 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3606 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3607 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3609 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3610 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3611 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3612 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3613 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3614 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3615 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3616 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3617 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3618 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3619 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3621 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3622 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3623 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3624 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3625 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3626 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3627 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3628 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3629 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3630 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3631 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3632 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3633 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3634 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3635 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3636 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3644 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3645 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3646 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3647 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3648 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3649 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3650 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3651 VM_SV_WritePicture, // #501
3653 VM_whichpack, // #503 string(string) whichpack = #503;
3660 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3661 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3662 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3663 VM_uri_get, // #513 float(string uri, float id, [string post_contenttype, string post_delim, [float buf]]) uri_get = #513; (DP_QC_URI_GET, DP_QC_URI_POST)
3664 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3665 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3666 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3667 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3668 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3669 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3679 VM_loadfromdata, // #529
3680 VM_loadfromfile, // #530
3681 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3683 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3684 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3690 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3691 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3692 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3755 VM_callfunction, // #605
3756 VM_writetofile, // #606
3757 VM_isfunction, // #607
3763 VM_parseentitydata, // #613
3774 VM_SV_getextresponse, // #624 string getextresponse(void)
3777 VM_sprintf, // #627 string sprintf(string format, ...)
3778 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3779 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3783 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3785 void VM_SV_Cmd_Init(void)
3790 void VM_SV_Cmd_Reset(void)
3792 World_End(&sv.world);
3793 if(PRVM_serverfunction(SV_Shutdown))
3795 func_t s = PRVM_serverfunction(SV_Shutdown);
3796 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3797 PRVM_ExecuteProgram(s,"SV_Shutdown() required");