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 "
146 "DP_SND_GETSOUNDTIME "
148 "DP_VIDEO_SUBTITLES "
152 "DP_SV_BOUNCEFACTOR "
153 "DP_SV_CLIENTCAMERA "
154 "DP_SV_CLIENTCOLORS "
157 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
158 "DP_SV_DISCARDABLEDEMO "
159 "DP_SV_DRAWONLYTOCLIENT "
162 "DP_SV_ENTITYCONTENTSTRANSITION "
163 "DP_SV_MODELFLAGS_AS_EFFECTS "
164 "DP_SV_MOVETYPESTEP_LANDEVENT "
166 "DP_SV_NODRAWTOCLIENT "
167 "DP_SV_ONENTITYNOSPAWNFUNCTION "
168 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
170 "DP_SV_PING_PACKETLOSS "
171 "DP_SV_PLAYERPHYSICS "
173 "DP_SV_POINTPARTICLES "
175 "DP_SV_PRECACHEANYTIME "
179 "DP_SV_ROTATINGBMODEL "
183 "DP_SV_SPAWNFUNC_PREFIX "
184 "DP_SV_WRITEPICTURE "
185 "DP_SV_WRITEUNTERMINATEDSTRING "
189 "DP_TE_EXPLOSIONRGB "
191 "DP_TE_PARTICLECUBE "
192 "DP_TE_PARTICLERAIN "
193 "DP_TE_PARTICLESNOW "
195 "DP_TE_QUADEFFECTS1 "
198 "DP_TE_STANDARDEFFECTBUILTINS "
199 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
203 "FTE_CSQC_SKELETONOBJECTS "
206 "KRIMZON_SV_PARSECLIENTCOMMAND "
209 "NEXUIZ_PLAYERMODEL "
211 "PRYDON_CLIENTCURSOR "
212 "TENEBRAE_GFX_DLIGHTS "
215 //"EXT_CSQC " // not ready yet
222 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.
224 setorigin (entity, origin)
227 static void VM_SV_setorigin (void)
232 VM_SAFEPARMCOUNT(2, VM_setorigin);
234 e = PRVM_G_EDICT(OFS_PARM0);
235 if (e == prog->edicts)
237 VM_Warning("setorigin: can not modify world entity\n");
240 if (e->priv.server->free)
242 VM_Warning("setorigin: can not modify free entity\n");
245 org = PRVM_G_VECTOR(OFS_PARM1);
246 VectorCopy (org, PRVM_serveredictvector(e, origin));
250 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
251 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
255 for (i=0 ; i<3 ; i++)
257 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
259 // set derived values
260 VectorCopy (min, PRVM_serveredictvector(e, mins));
261 VectorCopy (max, PRVM_serveredictvector(e, maxs));
262 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
271 the size box is rotated by the current angle
272 LordHavoc: no it isn't...
274 setsize (entity, minvector, maxvector)
277 static void VM_SV_setsize (void)
282 VM_SAFEPARMCOUNT(3, VM_setsize);
284 e = PRVM_G_EDICT(OFS_PARM0);
285 if (e == prog->edicts)
287 VM_Warning("setsize: can not modify world entity\n");
290 if (e->priv.server->free)
292 VM_Warning("setsize: can not modify free entity\n");
295 min = PRVM_G_VECTOR(OFS_PARM1);
296 max = PRVM_G_VECTOR(OFS_PARM2);
297 SetMinMaxSize (e, min, max, false);
305 setmodel(entity, model)
308 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
309 static void VM_SV_setmodel (void)
315 VM_SAFEPARMCOUNT(2, VM_setmodel);
317 e = PRVM_G_EDICT(OFS_PARM0);
318 if (e == prog->edicts)
320 VM_Warning("setmodel: can not modify world entity\n");
323 if (e->priv.server->free)
325 VM_Warning("setmodel: can not modify free entity\n");
328 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
329 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
330 PRVM_serveredictfloat(e, modelindex) = i;
332 mod = SV_GetModelByIndex(i);
336 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
337 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
339 SetMinMaxSize (e, quakemins, quakemaxs, true);
342 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
349 single print to a specific client
351 sprint(clientent, value)
354 static void VM_SV_sprint (void)
358 char string[VM_STRINGTEMP_LENGTH];
360 VM_VarString(1, string, sizeof(string));
362 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
364 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
365 // LordHavoc: div0 requested that sprintto world operate like print
372 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
374 VM_Warning("tried to centerprint to a non-client\n");
378 client = svs.clients + entnum-1;
379 if (!client->netconnection)
382 MSG_WriteChar(&client->netconnection->message,svc_print);
383 MSG_WriteString(&client->netconnection->message, string);
391 single print to a specific client
393 centerprint(clientent, value)
396 static void VM_SV_centerprint (void)
400 char string[VM_STRINGTEMP_LENGTH];
402 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
404 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
406 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
408 VM_Warning("tried to centerprint to a non-client\n");
412 client = svs.clients + entnum-1;
413 if (!client->netconnection)
416 VM_VarString(1, string, sizeof(string));
417 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
418 MSG_WriteString(&client->netconnection->message, string);
425 particle(origin, color, count)
428 static void VM_SV_particle (void)
434 VM_SAFEPARMCOUNT(4, VM_SV_particle);
436 org = PRVM_G_VECTOR(OFS_PARM0);
437 dir = PRVM_G_VECTOR(OFS_PARM1);
438 color = PRVM_G_FLOAT(OFS_PARM2);
439 count = PRVM_G_FLOAT(OFS_PARM3);
440 SV_StartParticle (org, dir, (int)color, (int)count);
450 static void VM_SV_ambientsound (void)
454 float vol, attenuation;
457 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
459 pos = PRVM_G_VECTOR (OFS_PARM0);
460 samp = PRVM_G_STRING(OFS_PARM1);
461 vol = PRVM_G_FLOAT(OFS_PARM2);
462 attenuation = PRVM_G_FLOAT(OFS_PARM3);
464 // check to see if samp was properly precached
465 soundnum = SV_SoundIndex(samp, 1);
473 // add an svc_spawnambient command to the level signon packet
476 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
478 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
480 MSG_WriteVector(&sv.signon, pos, sv.protocol);
482 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
483 MSG_WriteShort (&sv.signon, soundnum);
485 MSG_WriteByte (&sv.signon, soundnum);
487 MSG_WriteByte (&sv.signon, (int)(vol*255));
488 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
496 Each entity can have eight independant sound sources, like voice,
499 Channel 0 is an auto-allocate channel, the others override anything
500 already running on that entity/channel pair.
502 An attenuation of 0 will play full volume everywhere in the level.
503 Larger attenuations will drop off.
507 static void VM_SV_sound (void)
511 prvm_edict_t *entity;
515 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
517 entity = PRVM_G_EDICT(OFS_PARM0);
518 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
519 sample = PRVM_G_STRING(OFS_PARM2);
520 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
521 attenuation = PRVM_G_FLOAT(OFS_PARM4);
524 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
528 if (volume < 0 || volume > 255)
530 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
534 if (attenuation < 0 || attenuation > 4)
536 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
540 if (channel < 0 || channel > 7)
542 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
546 SV_StartSound (entity, channel, sample, volume, attenuation);
553 Follows the same logic as VM_SV_sound, except instead of
554 an entity, an origin for the sound is provided, and channel
555 is omitted (since no entity is being tracked).
559 static void VM_SV_pointsound(void)
566 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
568 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
569 sample = PRVM_G_STRING(OFS_PARM1);
570 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
571 attenuation = PRVM_G_FLOAT(OFS_PARM3);
573 if (volume < 0 || volume > 255)
575 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
579 if (attenuation < 0 || attenuation > 4)
581 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
585 SV_StartPointSound (org, sample, volume, attenuation);
592 Used for use tracing and shot targeting
593 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
594 if the tryents flag is set.
596 traceline (vector1, vector2, movetype, ignore)
599 static void VM_SV_traceline (void)
606 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
608 prog->xfunction->builtinsprofile += 30;
610 v1 = PRVM_G_VECTOR(OFS_PARM0);
611 v2 = PRVM_G_VECTOR(OFS_PARM1);
612 move = (int)PRVM_G_FLOAT(OFS_PARM2);
613 ent = PRVM_G_EDICT(OFS_PARM3);
615 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]))
616 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));
618 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
620 VM_SetTraceGlobals(&trace);
628 Used for use tracing and shot targeting
629 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
630 if the tryents flag is set.
632 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
635 // LordHavoc: added this for my own use, VERY useful, similar to traceline
636 static void VM_SV_tracebox (void)
638 float *v1, *v2, *m1, *m2;
643 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
645 prog->xfunction->builtinsprofile += 30;
647 v1 = PRVM_G_VECTOR(OFS_PARM0);
648 m1 = PRVM_G_VECTOR(OFS_PARM1);
649 m2 = PRVM_G_VECTOR(OFS_PARM2);
650 v2 = PRVM_G_VECTOR(OFS_PARM3);
651 move = (int)PRVM_G_FLOAT(OFS_PARM4);
652 ent = PRVM_G_EDICT(OFS_PARM5);
654 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]))
655 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));
657 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
659 VM_SetTraceGlobals(&trace);
662 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
667 vec3_t original_origin;
668 vec3_t original_velocity;
669 vec3_t original_angles;
670 vec3_t original_avelocity;
673 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
674 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
675 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
676 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
678 gravity = PRVM_serveredictfloat(tossent, gravity);
681 gravity *= sv_gravity.value * 0.025;
683 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
685 SV_CheckVelocity (tossent);
686 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
687 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
688 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
689 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
690 trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
691 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
692 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
694 if (trace.fraction < 1)
698 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
699 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
700 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
701 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
706 static void VM_SV_tracetoss (void)
710 prvm_edict_t *ignore;
712 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
714 prog->xfunction->builtinsprofile += 600;
716 ent = PRVM_G_EDICT(OFS_PARM0);
717 if (ent == prog->edicts)
719 VM_Warning("tracetoss: can not use world entity\n");
722 ignore = PRVM_G_EDICT(OFS_PARM1);
724 trace = SV_Trace_Toss (ent, ignore);
726 VM_SetTraceGlobals(&trace);
729 //============================================================================
731 static int checkpvsbytes;
732 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
734 static int VM_SV_newcheckclient (int check)
740 // cycle to the next one
742 check = bound(1, check, svs.maxclients);
743 if (check == svs.maxclients)
751 prog->xfunction->builtinsprofile++;
753 if (i == svs.maxclients+1)
755 // look up the client's edict
756 ent = PRVM_EDICT_NUM(i);
757 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
758 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
760 // found a valid client (possibly the same one again)
764 // get the PVS for the entity
765 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
767 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
768 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
777 Returns a client (or object that has a client enemy) that would be a
780 If there is more than one valid option, they are cycled each frame
782 If (self.origin + self.viewofs) is not in the PVS of the current target,
783 it is not returned at all.
788 int c_invis, c_notvis;
789 static void VM_SV_checkclient (void)
791 prvm_edict_t *ent, *self;
794 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
796 // find a new check if on a new frame
797 if (sv.time - sv.lastchecktime >= 0.1)
799 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
800 sv.lastchecktime = sv.time;
803 // return check if it might be visible
804 ent = PRVM_EDICT_NUM(sv.lastcheck);
805 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
807 VM_RETURN_EDICT(prog->edicts);
811 // if current entity can't possibly see the check entity, return 0
812 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
813 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
814 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
817 VM_RETURN_EDICT(prog->edicts);
821 // might be able to see it
823 VM_RETURN_EDICT(ent);
826 //============================================================================
832 Checks if an entity is in a point's PVS.
833 Should be fast but can be inexact.
835 float checkpvs(vector viewpos, entity viewee) = #240;
838 static void VM_SV_checkpvs (void)
841 prvm_edict_t *viewee;
846 unsigned char fatpvs[MAX_MAP_LEAFS/8];
849 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
850 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
851 viewee = PRVM_G_EDICT(OFS_PARM1);
853 if(viewee->priv.server->free)
855 VM_Warning("checkpvs: can not check free entity\n");
856 PRVM_G_FLOAT(OFS_RETURN) = 4;
861 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
863 // no PVS support on this worldmodel... darn
864 PRVM_G_FLOAT(OFS_RETURN) = 3;
867 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
870 // viewpos isn't in any PVS... darn
871 PRVM_G_FLOAT(OFS_RETURN) = 2;
874 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
876 // using fat PVS like FTEQW does (slow)
877 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
879 // no PVS support on this worldmodel... darn
880 PRVM_G_FLOAT(OFS_RETURN) = 3;
883 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
886 // viewpos isn't in any PVS... darn
887 PRVM_G_FLOAT(OFS_RETURN) = 2;
890 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
899 Sends text over to the client's execution buffer
901 stuffcmd (clientent, value, ...)
904 static void VM_SV_stuffcmd (void)
908 char string[VM_STRINGTEMP_LENGTH];
910 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
912 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
913 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
915 VM_Warning("Can't stuffcmd to a non-client\n");
919 VM_VarString(1, string, sizeof(string));
922 host_client = svs.clients + entnum-1;
923 Host_ClientCommands ("%s", string);
931 Returns a chain of entities that have origins within a spherical area
933 findradius (origin, radius)
936 static void VM_SV_findradius (void)
938 prvm_edict_t *ent, *chain;
939 vec_t radius, radius2;
940 vec3_t org, eorg, mins, maxs;
943 static prvm_edict_t *touchedicts[MAX_EDICTS];
946 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
949 chainfield = PRVM_G_INT(OFS_PARM2);
951 chainfield = prog->fieldoffsets.chain;
953 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
955 chain = (prvm_edict_t *)prog->edicts;
957 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
958 radius = PRVM_G_FLOAT(OFS_PARM1);
959 radius2 = radius * radius;
961 mins[0] = org[0] - (radius + 1);
962 mins[1] = org[1] - (radius + 1);
963 mins[2] = org[2] - (radius + 1);
964 maxs[0] = org[0] + (radius + 1);
965 maxs[1] = org[1] + (radius + 1);
966 maxs[2] = org[2] + (radius + 1);
967 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
968 if (numtouchedicts > MAX_EDICTS)
970 // this never happens
971 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
972 numtouchedicts = MAX_EDICTS;
974 for (i = 0;i < numtouchedicts;i++)
976 ent = touchedicts[i];
977 prog->xfunction->builtinsprofile++;
978 // Quake did not return non-solid entities but darkplaces does
979 // (note: this is the reason you can't blow up fallen zombies)
980 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
982 // LordHavoc: compare against bounding box rather than center so it
983 // doesn't miss large objects, and use DotProduct instead of Length
984 // for a major speedup
985 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
986 if (sv_gameplayfix_findradiusdistancetobox.integer)
988 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
989 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
990 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
993 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
994 if (DotProduct(eorg, eorg) < radius2)
996 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1001 VM_RETURN_EDICT(chain);
1004 static void VM_SV_precache_sound (void)
1006 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1007 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1010 static void VM_SV_precache_model (void)
1012 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1013 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1014 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1021 float(float yaw, float dist[, settrace]) walkmove
1024 static void VM_SV_walkmove (void)
1033 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1035 // assume failure if it returns early
1036 PRVM_G_FLOAT(OFS_RETURN) = 0;
1038 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1039 if (ent == prog->edicts)
1041 VM_Warning("walkmove: can not modify world entity\n");
1044 if (ent->priv.server->free)
1046 VM_Warning("walkmove: can not modify free entity\n");
1049 yaw = PRVM_G_FLOAT(OFS_PARM0);
1050 dist = PRVM_G_FLOAT(OFS_PARM1);
1051 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1053 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1056 yaw = yaw*M_PI*2 / 360;
1058 move[0] = cos(yaw)*dist;
1059 move[1] = sin(yaw)*dist;
1062 // save program state, because SV_movestep may call other progs
1063 oldf = prog->xfunction;
1064 oldself = PRVM_serverglobaledict(self);
1066 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1069 // restore program state
1070 prog->xfunction = oldf;
1071 PRVM_serverglobaledict(self) = oldself;
1081 static void VM_SV_droptofloor (void)
1087 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1089 // assume failure if it returns early
1090 PRVM_G_FLOAT(OFS_RETURN) = 0;
1092 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1093 if (ent == prog->edicts)
1095 VM_Warning("droptofloor: can not modify world entity\n");
1098 if (ent->priv.server->free)
1100 VM_Warning("droptofloor: can not modify free entity\n");
1104 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1107 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1108 SV_UnstickEntity(ent);
1110 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1111 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1114 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]);
1115 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1116 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1117 VectorSubtract(trace.endpos, offset, trace.endpos);
1118 if (trace.startsolid)
1120 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]);
1121 SV_UnstickEntity(ent);
1123 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1124 PRVM_serveredictedict(ent, groundentity) = 0;
1125 PRVM_G_FLOAT(OFS_RETURN) = 1;
1127 else if (trace.fraction < 1)
1129 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]);
1130 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1131 SV_UnstickEntity(ent);
1133 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1134 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1135 PRVM_G_FLOAT(OFS_RETURN) = 1;
1136 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1137 ent->priv.server->suspendedinairflag = true;
1142 if (trace.fraction != 1)
1144 if (trace.fraction < 1)
1145 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1147 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1148 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1149 PRVM_G_FLOAT(OFS_RETURN) = 1;
1150 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1151 ent->priv.server->suspendedinairflag = true;
1160 void(float style, string value) lightstyle
1163 static void VM_SV_lightstyle (void)
1170 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1172 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1173 val = PRVM_G_STRING(OFS_PARM1);
1175 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1176 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1179 // change the string in sv
1180 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1182 // send message to all clients on this server
1183 if (sv.state != ss_active)
1186 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1188 if (client->active && client->netconnection)
1190 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1191 MSG_WriteChar (&client->netconnection->message,style);
1192 MSG_WriteString (&client->netconnection->message, val);
1202 static void VM_SV_checkbottom (void)
1204 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1205 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1213 static void VM_SV_pointcontents (void)
1215 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1216 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1223 Pick a vector for the player to shoot along
1224 vector aim(entity, missilespeed)
1227 static void VM_SV_aim (void)
1229 prvm_edict_t *ent, *check, *bestent;
1230 vec3_t start, dir, end, bestdir;
1233 float dist, bestdist;
1236 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1238 // assume failure if it returns early
1239 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1240 // if sv_aim is so high it can't possibly accept anything, skip out early
1241 if (sv_aim.value >= 1)
1244 ent = PRVM_G_EDICT(OFS_PARM0);
1245 if (ent == prog->edicts)
1247 VM_Warning("aim: can not use world entity\n");
1250 if (ent->priv.server->free)
1252 VM_Warning("aim: can not use free entity\n");
1255 //speed = PRVM_G_FLOAT(OFS_PARM1);
1257 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1260 // try sending a trace straight
1261 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1262 VectorMA (start, 2048, dir, end);
1263 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1264 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1265 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1267 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1272 // try all possible entities
1273 VectorCopy (dir, bestdir);
1274 bestdist = sv_aim.value;
1277 check = PRVM_NEXT_EDICT(prog->edicts);
1278 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1280 prog->xfunction->builtinsprofile++;
1281 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1285 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1286 continue; // don't aim at teammate
1287 for (j=0 ; j<3 ; j++)
1288 end[j] = PRVM_serveredictvector(check, origin)[j]
1289 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1290 VectorSubtract (end, start, dir);
1291 VectorNormalize (dir);
1292 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1293 if (dist < bestdist)
1294 continue; // to far to turn
1295 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1296 if (tr.ent == check)
1297 { // can shoot at this one
1305 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1306 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1307 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1309 VectorNormalize (end);
1310 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1314 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1319 ===============================================================================
1323 ===============================================================================
1326 #define MSG_BROADCAST 0 // unreliable to all
1327 #define MSG_ONE 1 // reliable to one (msg_entity)
1328 #define MSG_ALL 2 // reliable to all
1329 #define MSG_INIT 3 // write to the init string
1330 #define MSG_ENTITY 5
1332 sizebuf_t *WriteDest (void)
1338 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1342 return &sv.datagram;
1345 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1346 entnum = PRVM_NUM_FOR_EDICT(ent);
1347 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1349 VM_Warning ("WriteDest: tried to write to non-client\n");
1350 return &sv.reliable_datagram;
1353 return &svs.clients[entnum-1].netconnection->message;
1356 VM_Warning ("WriteDest: bad destination\n");
1358 return &sv.reliable_datagram;
1364 return sv.writeentitiestoclient_msg;
1370 static void VM_SV_WriteByte (void)
1372 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1373 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1376 static void VM_SV_WriteChar (void)
1378 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1379 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1382 static void VM_SV_WriteShort (void)
1384 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1385 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1388 static void VM_SV_WriteLong (void)
1390 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1391 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1394 static void VM_SV_WriteAngle (void)
1396 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1397 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1400 static void VM_SV_WriteCoord (void)
1402 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1403 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1406 static void VM_SV_WriteString (void)
1408 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1409 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1412 static void VM_SV_WriteUnterminatedString (void)
1414 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1415 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1419 static void VM_SV_WriteEntity (void)
1421 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1422 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1425 // writes a picture as at most size bytes of data
1427 // IMGNAME \0 SIZE(short) IMGDATA
1428 // if failed to read/compress:
1430 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1431 static void VM_SV_WritePicture (void)
1433 const char *imgname;
1437 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1439 imgname = PRVM_G_STRING(OFS_PARM1);
1440 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1444 MSG_WriteString(WriteDest(), imgname);
1445 if(Image_Compress(imgname, size, &buf, &size))
1448 MSG_WriteShort(WriteDest(), size);
1449 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1454 MSG_WriteShort(WriteDest(), 0);
1458 //////////////////////////////////////////////////////////
1460 static void VM_SV_makestatic (void)
1465 // allow 0 parameters due to an id1 qc bug in which this function is used
1466 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1467 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1469 if (prog->argc >= 1)
1470 ent = PRVM_G_EDICT(OFS_PARM0);
1472 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1473 if (ent == prog->edicts)
1475 VM_Warning("makestatic: can not modify world entity\n");
1478 if (ent->priv.server->free)
1480 VM_Warning("makestatic: can not modify free entity\n");
1485 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1490 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1491 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1492 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1494 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1496 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1497 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1498 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1502 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1503 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1504 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1507 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1508 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1509 for (i=0 ; i<3 ; i++)
1511 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1512 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1515 // throw the entity away now
1519 //=============================================================================
1526 static void VM_SV_setspawnparms (void)
1532 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1534 ent = PRVM_G_EDICT(OFS_PARM0);
1535 i = PRVM_NUM_FOR_EDICT(ent);
1536 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1538 Con_Print("tried to setspawnparms on a non-client\n");
1542 // copy spawn parms out of the client_t
1543 client = svs.clients + i-1;
1544 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1545 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1552 Returns a color vector indicating the lighting at the requested point.
1554 (Internal Operation note: actually measures the light beneath the point, just like
1555 the model lighting on the client)
1560 static void VM_SV_getlight (void)
1562 vec3_t ambientcolor, diffusecolor, diffusenormal;
1564 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1565 p = PRVM_G_VECTOR(OFS_PARM0);
1566 VectorClear(ambientcolor);
1567 VectorClear(diffusecolor);
1568 VectorClear(diffusenormal);
1569 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1570 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1571 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1576 unsigned char type; // 1/2/8 or other value if isn't used
1580 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1581 static int vm_customstats_last;
1583 void VM_CustomStats_Clear (void)
1587 Z_Free(vm_customstats);
1588 vm_customstats = NULL;
1589 vm_customstats_last = -1;
1593 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1601 for(i=0; i<vm_customstats_last+1 ;i++)
1603 if(!vm_customstats[i].type)
1605 switch(vm_customstats[i].type)
1607 //string as 16 bytes
1610 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1611 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1612 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1613 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1614 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1616 //float field sent as-is
1618 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1620 //integer value of float field
1622 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1630 // void(float index, float type, .void field) SV_AddStat = #232;
1631 // Set up an auto-sent player stat.
1632 // Client's get thier own fields sent to them. Index may not be less than 32.
1633 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1634 // 1: string (4 stats carrying a total of 16 charactures)
1635 // 2: float (one stat, float converted to an integer for transportation)
1636 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1637 static void VM_SV_AddStat (void)
1642 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1646 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1649 VM_Warning("PF_SV_AddStat: not enough memory\n");
1653 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1654 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1655 off = PRVM_G_INT (OFS_PARM2);
1660 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1663 if(i >= (MAX_CL_STATS-32))
1665 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1668 if(i > (MAX_CL_STATS-32-4) && type == 1)
1670 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1673 vm_customstats[i].type = type;
1674 vm_customstats[i].fieldoffset = off;
1675 if(vm_customstats_last < i)
1676 vm_customstats_last = i;
1683 copies data from one entity to another
1685 copyentity(src, dst)
1688 static void VM_SV_copyentity (void)
1690 prvm_edict_t *in, *out;
1691 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1692 in = PRVM_G_EDICT(OFS_PARM0);
1693 if (in == prog->edicts)
1695 VM_Warning("copyentity: can not read world entity\n");
1698 if (in->priv.server->free)
1700 VM_Warning("copyentity: can not read free entity\n");
1703 out = PRVM_G_EDICT(OFS_PARM1);
1704 if (out == prog->edicts)
1706 VM_Warning("copyentity: can not modify world entity\n");
1709 if (out->priv.server->free)
1711 VM_Warning("copyentity: can not modify free entity\n");
1714 memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
1723 sets the color of a client and broadcasts the update to all connected clients
1725 setcolor(clientent, value)
1728 static void VM_SV_setcolor (void)
1733 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1734 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1735 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1737 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1739 Con_Print("tried to setcolor a non-client\n");
1743 client = svs.clients + entnum-1;
1746 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1747 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1750 if (client->old_colors != client->colors)
1752 client->old_colors = client->colors;
1753 // send notification to all clients
1754 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1755 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1756 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1764 effect(origin, modelname, startframe, framecount, framerate)
1767 static void VM_SV_effect (void)
1771 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1772 s = PRVM_G_STRING(OFS_PARM1);
1775 VM_Warning("effect: no model specified\n");
1779 i = SV_ModelIndex(s, 1);
1782 VM_Warning("effect: model not precached\n");
1786 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1788 VM_Warning("effect: framecount < 1\n");
1792 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1794 VM_Warning("effect: framerate < 1\n");
1798 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));
1801 static void VM_SV_te_blood (void)
1803 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1804 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1806 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1807 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1809 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1810 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1813 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1814 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1815 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1817 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1818 SV_FlushBroadcastMessages();
1821 static void VM_SV_te_bloodshower (void)
1823 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1824 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1826 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1827 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1830 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1831 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1833 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1834 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1835 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1837 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1839 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1840 SV_FlushBroadcastMessages();
1843 static void VM_SV_te_explosionrgb (void)
1845 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1846 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1847 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1849 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1850 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1851 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1853 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1854 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1855 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1856 SV_FlushBroadcastMessages();
1859 static void VM_SV_te_particlecube (void)
1861 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1862 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1864 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1865 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1868 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1869 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1873 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1875 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1876 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1877 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1879 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1881 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1882 // gravity true/false
1883 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1885 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1886 SV_FlushBroadcastMessages();
1889 static void VM_SV_te_particlerain (void)
1891 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1892 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1894 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1895 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1909 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1911 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1912 SV_FlushBroadcastMessages();
1915 static void VM_SV_te_particlesnow (void)
1917 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1918 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1920 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1921 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1923 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1924 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1925 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1935 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1937 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1938 SV_FlushBroadcastMessages();
1941 static void VM_SV_te_spark (void)
1943 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1944 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1946 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1947 MSG_WriteByte(&sv.datagram, TE_SPARK);
1949 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1950 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1953 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1954 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1955 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1957 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1958 SV_FlushBroadcastMessages();
1961 static void VM_SV_te_gunshotquad (void)
1963 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1964 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1965 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1970 SV_FlushBroadcastMessages();
1973 static void VM_SV_te_spikequad (void)
1975 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1976 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1977 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1979 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1980 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1982 SV_FlushBroadcastMessages();
1985 static void VM_SV_te_superspikequad (void)
1987 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1988 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1989 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1991 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1992 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1993 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1994 SV_FlushBroadcastMessages();
1997 static void VM_SV_te_explosionquad (void)
1999 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2000 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2001 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2004 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2005 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2006 SV_FlushBroadcastMessages();
2009 static void VM_SV_te_smallflash (void)
2011 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2012 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2013 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2015 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2016 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2017 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2018 SV_FlushBroadcastMessages();
2021 static void VM_SV_te_customflash (void)
2023 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2024 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2026 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2027 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2029 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2030 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2031 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2033 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2035 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2037 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2038 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2039 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2040 SV_FlushBroadcastMessages();
2043 static void VM_SV_te_gunshot (void)
2045 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2046 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2047 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2049 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2050 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2052 SV_FlushBroadcastMessages();
2055 static void VM_SV_te_spike (void)
2057 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2058 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2059 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2061 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2062 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2063 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2064 SV_FlushBroadcastMessages();
2067 static void VM_SV_te_superspike (void)
2069 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2070 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2071 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2074 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2075 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2076 SV_FlushBroadcastMessages();
2079 static void VM_SV_te_explosion (void)
2081 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2082 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2083 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2085 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2086 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2087 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2088 SV_FlushBroadcastMessages();
2091 static void VM_SV_te_tarexplosion (void)
2093 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2094 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2095 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2097 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2098 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2099 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2100 SV_FlushBroadcastMessages();
2103 static void VM_SV_te_wizspike (void)
2105 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2106 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2107 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2109 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2110 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2111 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2112 SV_FlushBroadcastMessages();
2115 static void VM_SV_te_knightspike (void)
2117 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2118 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2119 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2121 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2122 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2123 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2124 SV_FlushBroadcastMessages();
2127 static void VM_SV_te_lavasplash (void)
2129 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2130 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2131 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2133 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2134 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2135 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2136 SV_FlushBroadcastMessages();
2139 static void VM_SV_te_teleport (void)
2141 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2142 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2143 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2145 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2146 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2147 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2148 SV_FlushBroadcastMessages();
2151 static void VM_SV_te_explosion2 (void)
2153 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2154 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2155 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2157 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2158 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2159 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2161 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2162 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2163 SV_FlushBroadcastMessages();
2166 static void VM_SV_te_lightning1 (void)
2168 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2169 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2170 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2172 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2174 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2175 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2176 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2178 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2179 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2180 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2181 SV_FlushBroadcastMessages();
2184 static void VM_SV_te_lightning2 (void)
2186 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2187 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2188 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2190 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2192 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2193 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2194 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2196 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2197 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2198 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2199 SV_FlushBroadcastMessages();
2202 static void VM_SV_te_lightning3 (void)
2204 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2205 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2206 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2208 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2210 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2211 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2212 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2214 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2215 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2216 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2217 SV_FlushBroadcastMessages();
2220 static void VM_SV_te_beam (void)
2222 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2223 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2224 MSG_WriteByte(&sv.datagram, TE_BEAM);
2226 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2230 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2232 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2234 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2235 SV_FlushBroadcastMessages();
2238 static void VM_SV_te_plasmaburn (void)
2240 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2241 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2242 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2243 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2244 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2245 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2246 SV_FlushBroadcastMessages();
2249 static void VM_SV_te_flamejet (void)
2251 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2252 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2253 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2255 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2256 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2257 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2259 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2260 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2261 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2263 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2264 SV_FlushBroadcastMessages();
2267 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2268 //this function originally written by KrimZon, made shorter by LordHavoc
2269 static void VM_SV_clientcommand (void)
2271 client_t *temp_client;
2273 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2275 //find client for this entity
2276 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2277 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2279 Con_Print("PF_clientcommand: entity is not a client\n");
2283 temp_client = host_client;
2284 host_client = svs.clients + i;
2285 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2286 host_client = temp_client;
2289 //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)
2290 static void VM_SV_setattachment (void)
2292 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2293 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2294 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2297 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2299 if (e == prog->edicts)
2301 VM_Warning("setattachment: can not modify world entity\n");
2304 if (e->priv.server->free)
2306 VM_Warning("setattachment: can not modify free entity\n");
2310 if (tagentity == NULL)
2311 tagentity = prog->edicts;
2315 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2317 model = SV_GetModelFromEdict(tagentity);
2320 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2322 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);
2325 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));
2328 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2329 PRVM_serveredictfloat(e, tag_index) = tagindex;
2332 /////////////////////////////////////////
2333 // DP_MD3_TAGINFO extension coded by VorteX
2335 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2339 i = (int)PRVM_serveredictfloat(e, modelindex);
2340 if (i < 1 || i >= MAX_MODELS)
2343 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2346 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2353 Matrix4x4_CreateIdentity(tag_localmatrix);
2355 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2357 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2368 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2371 float pitchsign = 1;
2373 scale = PRVM_serveredictfloat(ent, scale);
2378 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);
2381 pitchsign = SV_GetPitchSign(ent);
2382 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);
2386 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2389 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2391 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2392 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2393 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2394 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2396 *out = identitymatrix;
2400 // Warnings/errors code:
2401 // 0 - normal (everything all-right)
2404 // 3 - null or non-precached model
2405 // 4 - no tags with requested index
2406 // 5 - runaway loop at attachment chain
2407 extern cvar_t cl_bob;
2408 extern cvar_t cl_bobcycle;
2409 extern cvar_t cl_bobup;
2410 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2413 int modelindex, attachloop;
2414 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2417 *out = identitymatrix; // warnings and errors return identical matrix
2419 if (ent == prog->edicts)
2421 if (ent->priv.server->free)
2424 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2425 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2428 model = SV_GetModelByIndex(modelindex);
2430 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2431 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2432 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2434 tagmatrix = identitymatrix;
2435 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2439 if (attachloop >= 256) // prevent runaway looping
2441 // apply transformation by child's tagindex on parent entity and then
2442 // by parent entity itself
2443 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2444 if (ret && attachloop == 0)
2446 SV_GetEntityMatrix(ent, &entitymatrix, false);
2447 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2448 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2449 // next iteration we process the parent entity
2450 if (PRVM_serveredictedict(ent, tag_entity))
2452 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2453 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2460 // RENDER_VIEWMODEL magic
2461 if (PRVM_serveredictedict(ent, viewmodelforclient))
2463 Matrix4x4_Copy(&tagmatrix, out);
2464 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2466 SV_GetEntityMatrix(ent, &entitymatrix, true);
2467 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2470 // Cl_bob, ported from rendering code
2471 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2474 // LordHavoc: this code is *weird*, but not replacable (I think it
2475 // should be done in QC on the server, but oh well, quake is quake)
2476 // LordHavoc: figured out bobup: the time at which the sin is at 180
2477 // degrees (which allows lengthening or squishing the peak or valley)
2478 cycle = sv.time/cl_bobcycle.value;
2479 cycle -= (int)cycle;
2480 if (cycle < cl_bobup.value)
2481 cycle = sin(M_PI * cycle / cl_bobup.value);
2483 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2484 // bob is proportional to velocity in the xy plane
2485 // (don't count Z, or jumping messes it up)
2486 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;
2487 bob = bob*0.3 + bob*0.7*cycle;
2488 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2495 //float(entity ent, string tagname) gettagindex;
2497 static void VM_SV_gettagindex (void)
2500 const char *tag_name;
2503 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2505 ent = PRVM_G_EDICT(OFS_PARM0);
2506 tag_name = PRVM_G_STRING(OFS_PARM1);
2508 if (ent == prog->edicts)
2510 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2513 if (ent->priv.server->free)
2515 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2520 if (!SV_GetModelFromEdict(ent))
2521 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2524 tag_index = SV_GetTagIndex(ent, tag_name);
2526 if(developer_extra.integer)
2527 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2529 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2532 //vector(entity ent, float tagindex) gettaginfo;
2533 static void VM_SV_gettaginfo (void)
2537 matrix4x4_t tag_matrix;
2538 matrix4x4_t tag_localmatrix;
2540 const char *tagname;
2542 vec3_t fo, le, up, trans;
2543 const dp_model_t *model;
2545 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2547 e = PRVM_G_EDICT(OFS_PARM0);
2548 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2550 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2551 Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
2552 VectorScale(le, -1, PRVM_serverglobalvector(v_right));
2553 model = SV_GetModelFromEdict(e);
2554 VM_GenerateFrameGroupBlend(e->priv.server->framegroupblend, e);
2555 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
2556 VM_UpdateEdictSkeleton(e, model, e->priv.server->frameblend);
2557 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2558 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2560 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2561 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(tagname) : 0;
2562 VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
2563 VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
2564 VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
2565 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2570 VM_Warning("gettagindex: can't affect world entity\n");
2573 VM_Warning("gettagindex: can't affect free entity\n");
2576 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2579 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2582 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2587 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2588 static void VM_SV_dropclient (void)
2591 client_t *oldhostclient;
2592 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2593 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2594 if (clientnum < 0 || clientnum >= svs.maxclients)
2596 VM_Warning("dropclient: not a client\n");
2599 if (!svs.clients[clientnum].active)
2601 VM_Warning("dropclient: that client slot is not connected\n");
2604 oldhostclient = host_client;
2605 host_client = svs.clients + clientnum;
2606 SV_DropClient(false);
2607 host_client = oldhostclient;
2610 //entity() spawnclient (DP_SV_BOTCLIENT)
2611 static void VM_SV_spawnclient (void)
2615 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2616 prog->xfunction->builtinsprofile += 2;
2618 for (i = 0;i < svs.maxclients;i++)
2620 if (!svs.clients[i].active)
2622 prog->xfunction->builtinsprofile += 100;
2623 SV_ConnectClient (i, NULL);
2624 // this has to be set or else ClientDisconnect won't be called
2625 // we assume the qc will call ClientConnect...
2626 svs.clients[i].clientconnectcalled = true;
2627 ed = PRVM_EDICT_NUM(i + 1);
2631 VM_RETURN_EDICT(ed);
2634 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2635 static void VM_SV_clienttype (void)
2638 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2639 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2640 if (clientnum < 0 || clientnum >= svs.maxclients)
2641 PRVM_G_FLOAT(OFS_RETURN) = 3;
2642 else if (!svs.clients[clientnum].active)
2643 PRVM_G_FLOAT(OFS_RETURN) = 0;
2644 else if (svs.clients[clientnum].netconnection)
2645 PRVM_G_FLOAT(OFS_RETURN) = 1;
2647 PRVM_G_FLOAT(OFS_RETURN) = 2;
2654 string(string key) serverkey
2657 void VM_SV_serverkey(void)
2659 char string[VM_STRINGTEMP_LENGTH];
2660 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2661 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2662 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2665 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2666 static void VM_SV_setmodelindex (void)
2671 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2673 e = PRVM_G_EDICT(OFS_PARM0);
2674 if (e == prog->edicts)
2676 VM_Warning("setmodelindex: can not modify world entity\n");
2679 if (e->priv.server->free)
2681 VM_Warning("setmodelindex: can not modify free entity\n");
2684 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2685 if (i <= 0 || i >= MAX_MODELS)
2687 VM_Warning("setmodelindex: invalid modelindex\n");
2690 if (!sv.model_precache[i][0])
2692 VM_Warning("setmodelindex: model not precached\n");
2696 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
2697 PRVM_serveredictfloat(e, modelindex) = i;
2699 mod = SV_GetModelByIndex(i);
2703 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2704 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2706 SetMinMaxSize (e, quakemins, quakemaxs, true);
2709 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2712 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2713 static void VM_SV_modelnameforindex (void)
2716 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2718 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2720 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2721 if (i <= 0 || i >= MAX_MODELS)
2723 VM_Warning("modelnameforindex: invalid modelindex\n");
2726 if (!sv.model_precache[i][0])
2728 VM_Warning("modelnameforindex: model not precached\n");
2732 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2735 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2736 static void VM_SV_particleeffectnum (void)
2739 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2740 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2743 PRVM_G_FLOAT(OFS_RETURN) = i;
2746 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2747 static void VM_SV_trailparticles (void)
2749 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2751 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2754 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2755 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2756 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2757 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2758 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2759 SV_FlushBroadcastMessages();
2762 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2763 static void VM_SV_pointparticles (void)
2765 int effectnum, count;
2767 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2769 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2772 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2773 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2774 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2775 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2776 if (count == 1 && !VectorLength2(vel))
2779 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2780 MSG_WriteShort(&sv.datagram, effectnum);
2781 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2785 // 1+2+12+12+2=29 bytes
2786 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2787 MSG_WriteShort(&sv.datagram, effectnum);
2788 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2789 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2790 MSG_WriteShort(&sv.datagram, count);
2793 SV_FlushBroadcastMessages();
2796 //PF_setpause, // void(float pause) setpause = #531;
2797 static void VM_SV_setpause(void) {
2799 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2800 if (pauseValue != 0) { //pause the game
2802 sv.pausedstart = Sys_DoubleTime();
2803 } else { //disable pause, in case it was enabled
2804 if (sv.paused != 0) {
2809 // send notification to all clients
2810 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2811 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2814 // #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.
2815 static void VM_SV_skel_create(void)
2817 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2818 dp_model_t *model = SV_GetModelByIndex(modelindex);
2819 skeleton_t *skeleton;
2821 PRVM_G_FLOAT(OFS_RETURN) = 0;
2822 if (!model || !model->num_bones)
2824 for (i = 0;i < MAX_EDICTS;i++)
2825 if (!prog->skeletons[i])
2827 if (i == MAX_EDICTS)
2829 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2830 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2831 skeleton->model = model;
2832 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2833 // initialize to identity matrices
2834 for (i = 0;i < skeleton->model->num_bones;i++)
2835 skeleton->relativetransforms[i] = identitymatrix;
2838 // #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
2839 static void VM_SV_skel_build(void)
2841 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2842 skeleton_t *skeleton;
2843 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2844 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2845 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2846 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2847 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2848 dp_model_t *model = SV_GetModelByIndex(modelindex);
2853 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2854 frameblend_t frameblend[MAX_FRAMEBLENDS];
2855 matrix4x4_t blendedmatrix;
2857 PRVM_G_FLOAT(OFS_RETURN) = 0;
2858 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2860 firstbone = max(0, firstbone);
2861 lastbone = min(lastbone, model->num_bones - 1);
2862 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2863 VM_GenerateFrameGroupBlend(framegroupblend, ed);
2864 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
2865 blendfrac = 1.0f - retainfrac;
2866 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2867 frameblend[numblends].lerp *= blendfrac;
2868 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2870 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2871 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2872 for (blendindex = 0;blendindex < numblends;blendindex++)
2874 Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2875 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2877 skeleton->relativetransforms[bonenum] = blendedmatrix;
2879 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2882 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2883 static void VM_SV_skel_get_numbones(void)
2885 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2886 skeleton_t *skeleton;
2887 PRVM_G_FLOAT(OFS_RETURN) = 0;
2888 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2890 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2893 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2894 static void VM_SV_skel_get_bonename(void)
2896 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2897 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2898 skeleton_t *skeleton;
2899 PRVM_G_INT(OFS_RETURN) = 0;
2900 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2902 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2904 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(skeleton->model->data_bones[bonenum].name);
2907 // #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)
2908 static void VM_SV_skel_get_boneparent(void)
2910 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2911 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2912 skeleton_t *skeleton;
2913 PRVM_G_FLOAT(OFS_RETURN) = 0;
2914 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2916 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2918 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2921 // #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
2922 static void VM_SV_skel_find_bone(void)
2924 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2925 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2926 skeleton_t *skeleton;
2927 PRVM_G_FLOAT(OFS_RETURN) = 0;
2928 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2930 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2933 // #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)
2934 static void VM_SV_skel_get_bonerel(void)
2936 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2937 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2938 skeleton_t *skeleton;
2940 vec3_t forward, left, up, origin;
2941 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2942 VectorClear(PRVM_clientglobalvector(v_forward));
2943 VectorClear(PRVM_clientglobalvector(v_right));
2944 VectorClear(PRVM_clientglobalvector(v_up));
2945 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2947 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2949 matrix = skeleton->relativetransforms[bonenum];
2950 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2951 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2952 VectorNegate(left, PRVM_clientglobalvector(v_right));
2953 VectorCopy(up, PRVM_clientglobalvector(v_up));
2954 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2957 // #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)
2958 static void VM_SV_skel_get_boneabs(void)
2960 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2961 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2962 skeleton_t *skeleton;
2965 vec3_t forward, left, up, origin;
2966 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2967 VectorClear(PRVM_clientglobalvector(v_forward));
2968 VectorClear(PRVM_clientglobalvector(v_right));
2969 VectorClear(PRVM_clientglobalvector(v_up));
2970 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2972 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2974 matrix = skeleton->relativetransforms[bonenum];
2975 // convert to absolute
2976 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
2979 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
2981 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2982 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2983 VectorNegate(left, PRVM_clientglobalvector(v_right));
2984 VectorCopy(up, PRVM_clientglobalvector(v_up));
2985 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2988 // #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)
2989 static void VM_SV_skel_set_bone(void)
2991 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2992 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2993 vec3_t forward, left, up, origin;
2994 skeleton_t *skeleton;
2996 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2998 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3000 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3001 VectorNegate(PRVM_clientglobalvector(v_right), left);
3002 VectorCopy(PRVM_clientglobalvector(v_up), up);
3003 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3004 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3005 skeleton->relativetransforms[bonenum] = matrix;
3008 // #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)
3009 static void VM_SV_skel_mul_bone(void)
3011 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3012 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3013 vec3_t forward, left, up, origin;
3014 skeleton_t *skeleton;
3017 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3019 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3021 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3022 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3023 VectorNegate(PRVM_clientglobalvector(v_right), left);
3024 VectorCopy(PRVM_clientglobalvector(v_up), up);
3025 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3026 temp = skeleton->relativetransforms[bonenum];
3027 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3030 // #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)
3031 static void VM_SV_skel_mul_bones(void)
3033 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3034 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3035 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3037 vec3_t forward, left, up, origin;
3038 skeleton_t *skeleton;
3041 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3043 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), 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 firstbone = max(0, firstbone);
3049 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3050 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3052 temp = skeleton->relativetransforms[bonenum];
3053 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3057 // #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
3058 static void VM_SV_skel_copybones(void)
3060 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3061 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3062 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3063 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3065 skeleton_t *skeletondst;
3066 skeleton_t *skeletonsrc;
3067 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3069 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3071 firstbone = max(0, firstbone);
3072 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3073 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3074 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3075 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3078 // #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)
3079 static void VM_SV_skel_delete(void)
3081 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3082 skeleton_t *skeleton;
3083 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3086 prog->skeletons[skeletonindex] = NULL;
3089 // #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
3090 static void VM_SV_frameforname(void)
3092 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3093 dp_model_t *model = SV_GetModelByIndex(modelindex);
3094 const char *name = PRVM_G_STRING(OFS_PARM1);
3096 PRVM_G_FLOAT(OFS_RETURN) = -1;
3097 if (!model || !model->animscenes)
3099 for (i = 0;i < model->numframes;i++)
3101 if (!strcasecmp(model->animscenes[i].name, name))
3103 PRVM_G_FLOAT(OFS_RETURN) = i;
3109 // #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.
3110 static void VM_SV_frameduration(void)
3112 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3113 dp_model_t *model = SV_GetModelByIndex(modelindex);
3114 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3115 PRVM_G_FLOAT(OFS_RETURN) = 0;
3116 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3118 if (model->animscenes[framenum].framerate)
3119 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3123 prvm_builtin_t vm_sv_builtins[] = {
3124 NULL, // #0 NULL function (not callable) (QUAKE)
3125 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3126 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3127 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3128 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3129 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3130 VM_break, // #6 void() break (QUAKE)
3131 VM_random, // #7 float() random (QUAKE)
3132 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3133 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3134 VM_error, // #10 void(string e) error (QUAKE)
3135 VM_objerror, // #11 void(string e) objerror (QUAKE)
3136 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3137 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3138 VM_spawn, // #14 entity() spawn (QUAKE)
3139 VM_remove, // #15 void(entity e) remove (QUAKE)
3140 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3141 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3142 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3143 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3144 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3145 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3146 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3147 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3148 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3149 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3150 VM_ftos, // #26 string(float f) ftos (QUAKE)
3151 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3152 VM_coredump, // #28 void() coredump (QUAKE)
3153 VM_traceon, // #29 void() traceon (QUAKE)
3154 VM_traceoff, // #30 void() traceoff (QUAKE)
3155 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3156 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3157 NULL, // #33 (QUAKE)
3158 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3159 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3160 VM_rint, // #36 float(float v) rint (QUAKE)
3161 VM_floor, // #37 float(float v) floor (QUAKE)
3162 VM_ceil, // #38 float(float v) ceil (QUAKE)
3163 NULL, // #39 (QUAKE)
3164 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3165 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3166 NULL, // #42 (QUAKE)
3167 VM_fabs, // #43 float(float f) fabs (QUAKE)
3168 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3169 VM_cvar, // #45 float(string s) cvar (QUAKE)
3170 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3171 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3172 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3173 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3174 NULL, // #50 (QUAKE)
3175 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3176 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3177 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3178 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3179 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3180 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3181 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3182 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3183 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3184 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3185 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3186 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3187 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3188 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3189 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3190 NULL, // #66 (QUAKE)
3191 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3192 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3193 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3194 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3195 NULL, // #71 (QUAKE)
3196 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3197 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3198 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3199 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3200 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3201 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3202 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3203 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3204 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3205 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3206 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3207 NULL, // #83 (QUAKE)
3208 NULL, // #84 (QUAKE)
3209 NULL, // #85 (QUAKE)
3210 NULL, // #86 (QUAKE)
3211 NULL, // #87 (QUAKE)
3212 NULL, // #88 (QUAKE)
3213 NULL, // #89 (QUAKE)
3214 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3215 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3216 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3217 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3218 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3219 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3220 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3221 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3222 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3223 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3224 // FrikaC and Telejano range #100-#199
3235 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3236 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3237 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3238 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3239 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3240 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3241 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3242 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3243 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3244 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3325 // FTEQW range #200-#299
3344 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3347 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3348 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3349 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3350 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3351 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3352 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3353 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3354 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3355 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3356 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3358 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3366 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3389 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.
3390 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
3391 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3392 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3393 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)
3394 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
3395 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)
3396 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)
3397 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)
3398 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)
3399 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)
3400 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
3401 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)
3402 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
3403 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.
3426 // CSQC range #300-#399
3427 NULL, // #300 void() clearscene (EXT_CSQC)
3428 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3429 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3430 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3431 NULL, // #304 void() renderscene (EXT_CSQC)
3432 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3433 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3434 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3435 NULL, // #308 void() R_EndPolygon
3437 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3438 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3442 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3443 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3444 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3445 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3446 NULL, // #319 void(string name) freepic (EXT_CSQC)
3447 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3448 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3449 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3450 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3451 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3452 NULL, // #325 void(void) drawresetcliparea
3457 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3458 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3459 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3460 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3461 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3462 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3463 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3464 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3465 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3466 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3467 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3468 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3469 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3470 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3471 NULL, // #344 vector() getmousepos (EXT_CSQC)
3472 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3473 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3474 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3475 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3476 NULL, // #349 float() isdemo (EXT_CSQC)
3477 VM_isserver, // #350 float() isserver (EXT_CSQC)
3478 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3479 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3480 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3481 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3487 NULL, // #360 float() readbyte (EXT_CSQC)
3488 NULL, // #361 float() readchar (EXT_CSQC)
3489 NULL, // #362 float() readshort (EXT_CSQC)
3490 NULL, // #363 float() readlong (EXT_CSQC)
3491 NULL, // #364 float() readcoord (EXT_CSQC)
3492 NULL, // #365 float() readangle (EXT_CSQC)
3493 NULL, // #366 string() readstring (EXT_CSQC)
3494 NULL, // #367 float() readfloat (EXT_CSQC)
3527 // LordHavoc's range #400-#499
3528 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3529 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3530 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3531 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3532 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3533 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3534 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3535 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3536 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)
3537 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3538 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3539 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3540 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3541 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3542 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3543 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3544 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3545 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3546 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3547 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3548 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3549 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3550 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3551 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3552 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3553 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3554 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3555 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3556 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3557 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3558 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3559 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3560 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3561 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3562 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3563 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3564 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3565 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3566 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3567 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3568 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3569 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3570 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3571 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3572 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3573 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3574 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3575 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3576 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3577 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3578 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3579 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3580 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3581 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3582 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3583 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3584 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3585 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3587 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3588 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3589 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3590 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3591 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3592 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3593 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3594 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3595 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3596 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3597 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3599 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3600 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3601 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3602 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3603 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3604 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3605 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3606 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3607 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3608 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3609 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3610 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3611 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3612 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3613 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3614 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3622 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3623 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3624 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3625 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3626 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3627 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3628 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3629 VM_SV_WritePicture, // #501
3631 VM_whichpack, // #503 string(string) whichpack = #503;
3638 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3639 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3640 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3641 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)
3642 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3643 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3644 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3645 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3646 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3647 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3657 VM_loadfromdata, // #529
3658 VM_loadfromfile, // #530
3659 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3661 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3662 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3668 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3669 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3670 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3733 VM_callfunction, // #605
3734 VM_writetofile, // #606
3735 VM_isfunction, // #607
3741 VM_parseentitydata, // #613
3752 VM_SV_getextresponse, // #624 string getextresponse(void)
3755 VM_sprintf, // #627 string sprintf(string format, ...)
3756 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3757 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3761 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3763 void VM_SV_Cmd_Init(void)
3768 void VM_SV_Cmd_Reset(void)
3770 World_End(&sv.world);
3771 if(PRVM_serverfunction(SV_Shutdown))
3773 func_t s = PRVM_serverfunction(SV_Shutdown);
3774 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3775 PRVM_ExecuteProgram(s,"SV_Shutdown() required");