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 "
56 "DP_GFX_EXTERNALTEXTURES "
57 "DP_GFX_EXTERNALTEXTURES_PERMAP "
59 "DP_GFX_MODEL_INTERPOLATION "
60 "DP_GFX_QUAKE3MODELTAGS "
64 "DP_GFX_FONTS_FREETYPE "
66 "DP_FONT_VARIABLEWIDTH "
68 "DP_HALFLIFE_MAP_CVAR "
71 "DP_LIGHTSTYLE_STATICVALUE "
75 "DP_MOVETYPEBOUNCEMISSILE "
78 "DP_QC_ASINACOSATANATAN2TAN "
84 "DP_QC_CVAR_DEFSTRING "
85 "DP_QC_CVAR_DESCRIPTION "
92 "DP_QC_EXTRESPONSEPACKET "
94 "DP_QC_FINDCHAINFLAGS "
95 "DP_QC_FINDCHAINFLOAT "
96 "DP_QC_FINDCHAIN_TOFIELD "
102 "DP_QC_GETSURFACETRIANGLE "
103 "DP_QC_GETSURFACEPOINTATTRIBUTE "
105 "DP_QC_GETTAGINFO_BONEPROPERTIES "
107 "DP_QC_GETTIME_CDTRACK "
110 "DP_QC_MULTIPLETEMPSTRINGS "
111 "DP_QC_NUM_FOR_EDICT "
113 "DP_QC_SINCOSSQRTPOW "
116 "DP_QC_STRINGBUFFERS "
117 "DP_QC_STRINGBUFFERS_CVARLIST "
118 "DP_QC_STRINGCOLORFUNCTIONS "
119 "DP_QC_STRING_CASE_FUNCTIONS "
121 "DP_QC_TOKENIZEBYSEPARATOR "
122 "DP_QC_TOKENIZE_CONSOLE "
125 "DP_QC_TRACE_MOVETYPE_HITMODEL "
126 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
127 "DP_QC_UNLIMITEDTEMPSTRINGS "
131 "DP_QC_VECTOANGLES_WITH_ROLL "
132 "DP_QC_VECTORVECTORS "
139 "DP_SKELETONOBJECTS "
140 "DP_SND_DIRECTIONLESSATTNNONE "
145 "DP_SND_GETSOUNDTIME "
147 "DP_VIDEO_SUBTITLES "
151 "DP_SV_BOUNCEFACTOR "
152 "DP_SV_CLIENTCAMERA "
153 "DP_SV_CLIENTCOLORS "
156 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
157 "DP_SV_DISCARDABLEDEMO "
158 "DP_SV_DRAWONLYTOCLIENT "
161 "DP_SV_ENTITYCONTENTSTRANSITION "
162 "DP_SV_MODELFLAGS_AS_EFFECTS "
163 "DP_SV_MOVETYPESTEP_LANDEVENT "
165 "DP_SV_NODRAWTOCLIENT "
166 "DP_SV_ONENTITYNOSPAWNFUNCTION "
167 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
169 "DP_SV_PING_PACKETLOSS "
170 "DP_SV_PLAYERPHYSICS "
172 "DP_SV_POINTPARTICLES "
174 "DP_SV_PRECACHEANYTIME "
178 "DP_SV_ROTATINGBMODEL "
182 "DP_SV_SPAWNFUNC_PREFIX "
183 "DP_SV_WRITEPICTURE "
184 "DP_SV_WRITEUNTERMINATEDSTRING "
188 "DP_TE_EXPLOSIONRGB "
190 "DP_TE_PARTICLECUBE "
191 "DP_TE_PARTICLERAIN "
192 "DP_TE_PARTICLESNOW "
194 "DP_TE_QUADEFFECTS1 "
197 "DP_TE_STANDARDEFFECTBUILTINS "
198 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
202 "FTE_CSQC_SKELETONOBJECTS "
205 "KRIMZON_SV_PARSECLIENTCOMMAND "
208 "NEXUIZ_PLAYERMODEL "
210 "PRYDON_CLIENTCURSOR "
211 "TENEBRAE_GFX_DLIGHTS "
214 //"EXT_CSQC " // not ready yet
221 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.
223 setorigin (entity, origin)
226 static void VM_SV_setorigin (void)
231 VM_SAFEPARMCOUNT(2, VM_setorigin);
233 e = PRVM_G_EDICT(OFS_PARM0);
234 if (e == prog->edicts)
236 VM_Warning("setorigin: can not modify world entity\n");
239 if (e->priv.server->free)
241 VM_Warning("setorigin: can not modify free entity\n");
244 org = PRVM_G_VECTOR(OFS_PARM1);
245 VectorCopy (org, PRVM_serveredictvector(e, origin));
249 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
250 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
254 for (i=0 ; i<3 ; i++)
256 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
258 // set derived values
259 VectorCopy (min, PRVM_serveredictvector(e, mins));
260 VectorCopy (max, PRVM_serveredictvector(e, maxs));
261 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
270 the size box is rotated by the current angle
271 LordHavoc: no it isn't...
273 setsize (entity, minvector, maxvector)
276 static void VM_SV_setsize (void)
281 VM_SAFEPARMCOUNT(3, VM_setsize);
283 e = PRVM_G_EDICT(OFS_PARM0);
284 if (e == prog->edicts)
286 VM_Warning("setsize: can not modify world entity\n");
289 if (e->priv.server->free)
291 VM_Warning("setsize: can not modify free entity\n");
294 min = PRVM_G_VECTOR(OFS_PARM1);
295 max = PRVM_G_VECTOR(OFS_PARM2);
296 SetMinMaxSize (e, min, max, false);
304 setmodel(entity, model)
307 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
308 static void VM_SV_setmodel (void)
314 VM_SAFEPARMCOUNT(2, VM_setmodel);
316 e = PRVM_G_EDICT(OFS_PARM0);
317 if (e == prog->edicts)
319 VM_Warning("setmodel: can not modify world entity\n");
322 if (e->priv.server->free)
324 VM_Warning("setmodel: can not modify free entity\n");
327 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
328 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
329 PRVM_serveredictfloat(e, modelindex) = i;
331 mod = SV_GetModelByIndex(i);
335 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
336 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
338 SetMinMaxSize (e, quakemins, quakemaxs, true);
341 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
348 single print to a specific client
350 sprint(clientent, value)
353 static void VM_SV_sprint (void)
357 char string[VM_STRINGTEMP_LENGTH];
359 VM_VarString(1, string, sizeof(string));
361 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
363 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
364 // LordHavoc: div0 requested that sprintto world operate like print
371 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
373 VM_Warning("tried to centerprint to a non-client\n");
377 client = svs.clients + entnum-1;
378 if (!client->netconnection)
381 MSG_WriteChar(&client->netconnection->message,svc_print);
382 MSG_WriteString(&client->netconnection->message, string);
390 single print to a specific client
392 centerprint(clientent, value)
395 static void VM_SV_centerprint (void)
399 char string[VM_STRINGTEMP_LENGTH];
401 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
403 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
405 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
407 VM_Warning("tried to centerprint to a non-client\n");
411 client = svs.clients + entnum-1;
412 if (!client->netconnection)
415 VM_VarString(1, string, sizeof(string));
416 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
417 MSG_WriteString(&client->netconnection->message, string);
424 particle(origin, color, count)
427 static void VM_SV_particle (void)
433 VM_SAFEPARMCOUNT(4, VM_SV_particle);
435 org = PRVM_G_VECTOR(OFS_PARM0);
436 dir = PRVM_G_VECTOR(OFS_PARM1);
437 color = PRVM_G_FLOAT(OFS_PARM2);
438 count = PRVM_G_FLOAT(OFS_PARM3);
439 SV_StartParticle (org, dir, (int)color, (int)count);
449 static void VM_SV_ambientsound (void)
453 float vol, attenuation;
456 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
458 pos = PRVM_G_VECTOR (OFS_PARM0);
459 samp = PRVM_G_STRING(OFS_PARM1);
460 vol = PRVM_G_FLOAT(OFS_PARM2);
461 attenuation = PRVM_G_FLOAT(OFS_PARM3);
463 // check to see if samp was properly precached
464 soundnum = SV_SoundIndex(samp, 1);
472 // add an svc_spawnambient command to the level signon packet
475 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
477 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
479 MSG_WriteVector(&sv.signon, pos, sv.protocol);
481 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
482 MSG_WriteShort (&sv.signon, soundnum);
484 MSG_WriteByte (&sv.signon, soundnum);
486 MSG_WriteByte (&sv.signon, (int)(vol*255));
487 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
495 Each entity can have eight independant sound sources, like voice,
498 Channel 0 is an auto-allocate channel, the others override anything
499 already running on that entity/channel pair.
501 An attenuation of 0 will play full volume everywhere in the level.
502 Larger attenuations will drop off.
506 static void VM_SV_sound (void)
510 prvm_edict_t *entity;
514 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
516 entity = PRVM_G_EDICT(OFS_PARM0);
517 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
518 sample = PRVM_G_STRING(OFS_PARM2);
519 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
520 attenuation = PRVM_G_FLOAT(OFS_PARM4);
523 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
527 if (volume < 0 || volume > 255)
529 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
533 if (attenuation < 0 || attenuation > 4)
535 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
539 if (channel < 0 || channel > 7)
541 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
545 SV_StartSound (entity, channel, sample, volume, attenuation);
552 Follows the same logic as VM_SV_sound, except instead of
553 an entity, an origin for the sound is provided, and channel
554 is omitted (since no entity is being tracked).
558 static void VM_SV_pointsound(void)
565 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
567 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
568 sample = PRVM_G_STRING(OFS_PARM1);
569 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
570 attenuation = PRVM_G_FLOAT(OFS_PARM3);
572 if (volume < 0 || volume > 255)
574 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
578 if (attenuation < 0 || attenuation > 4)
580 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
584 SV_StartPointSound (org, sample, volume, attenuation);
591 Used for use tracing and shot targeting
592 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
593 if the tryents flag is set.
595 traceline (vector1, vector2, movetype, ignore)
598 static void VM_SV_traceline (void)
605 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
607 prog->xfunction->builtinsprofile += 30;
609 v1 = PRVM_G_VECTOR(OFS_PARM0);
610 v2 = PRVM_G_VECTOR(OFS_PARM1);
611 move = (int)PRVM_G_FLOAT(OFS_PARM2);
612 ent = PRVM_G_EDICT(OFS_PARM3);
614 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]))
615 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));
617 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
619 VM_SetTraceGlobals(&trace);
627 Used for use tracing and shot targeting
628 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
629 if the tryents flag is set.
631 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
634 // LordHavoc: added this for my own use, VERY useful, similar to traceline
635 static void VM_SV_tracebox (void)
637 float *v1, *v2, *m1, *m2;
642 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
644 prog->xfunction->builtinsprofile += 30;
646 v1 = PRVM_G_VECTOR(OFS_PARM0);
647 m1 = PRVM_G_VECTOR(OFS_PARM1);
648 m2 = PRVM_G_VECTOR(OFS_PARM2);
649 v2 = PRVM_G_VECTOR(OFS_PARM3);
650 move = (int)PRVM_G_FLOAT(OFS_PARM4);
651 ent = PRVM_G_EDICT(OFS_PARM5);
653 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]))
654 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));
656 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
658 VM_SetTraceGlobals(&trace);
661 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
666 vec3_t original_origin;
667 vec3_t original_velocity;
668 vec3_t original_angles;
669 vec3_t original_avelocity;
672 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
673 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
674 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
675 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
677 gravity = PRVM_serveredictfloat(tossent, gravity);
680 gravity *= sv_gravity.value * 0.025;
682 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
684 SV_CheckVelocity (tossent);
685 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
686 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
687 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
688 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
689 trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
690 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
691 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
693 if (trace.fraction < 1)
697 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
698 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
699 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
700 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
705 static void VM_SV_tracetoss (void)
709 prvm_edict_t *ignore;
711 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
713 prog->xfunction->builtinsprofile += 600;
715 ent = PRVM_G_EDICT(OFS_PARM0);
716 if (ent == prog->edicts)
718 VM_Warning("tracetoss: can not use world entity\n");
721 ignore = PRVM_G_EDICT(OFS_PARM1);
723 trace = SV_Trace_Toss (ent, ignore);
725 VM_SetTraceGlobals(&trace);
728 //============================================================================
730 static int checkpvsbytes;
731 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
733 static int VM_SV_newcheckclient (int check)
739 // cycle to the next one
741 check = bound(1, check, svs.maxclients);
742 if (check == svs.maxclients)
750 prog->xfunction->builtinsprofile++;
752 if (i == svs.maxclients+1)
754 // look up the client's edict
755 ent = PRVM_EDICT_NUM(i);
756 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
757 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
759 // found a valid client (possibly the same one again)
763 // get the PVS for the entity
764 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
766 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
767 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
776 Returns a client (or object that has a client enemy) that would be a
779 If there is more than one valid option, they are cycled each frame
781 If (self.origin + self.viewofs) is not in the PVS of the current target,
782 it is not returned at all.
787 int c_invis, c_notvis;
788 static void VM_SV_checkclient (void)
790 prvm_edict_t *ent, *self;
793 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
795 // find a new check if on a new frame
796 if (sv.time - sv.lastchecktime >= 0.1)
798 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
799 sv.lastchecktime = sv.time;
802 // return check if it might be visible
803 ent = PRVM_EDICT_NUM(sv.lastcheck);
804 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
806 VM_RETURN_EDICT(prog->edicts);
810 // if current entity can't possibly see the check entity, return 0
811 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
812 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
813 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
816 VM_RETURN_EDICT(prog->edicts);
820 // might be able to see it
822 VM_RETURN_EDICT(ent);
825 //============================================================================
831 Checks if an entity is in a point's PVS.
832 Should be fast but can be inexact.
834 float checkpvs(vector viewpos, entity viewee) = #240;
837 static void VM_SV_checkpvs (void)
840 prvm_edict_t *viewee;
845 unsigned char fatpvs[MAX_MAP_LEAFS/8];
848 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
849 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
850 viewee = PRVM_G_EDICT(OFS_PARM1);
852 if(viewee->priv.server->free)
854 VM_Warning("checkpvs: can not check free entity\n");
855 PRVM_G_FLOAT(OFS_RETURN) = 4;
860 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
862 // no PVS support on this worldmodel... darn
863 PRVM_G_FLOAT(OFS_RETURN) = 3;
866 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
869 // viewpos isn't in any PVS... darn
870 PRVM_G_FLOAT(OFS_RETURN) = 2;
873 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
875 // using fat PVS like FTEQW does (slow)
876 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
878 // no PVS support on this worldmodel... darn
879 PRVM_G_FLOAT(OFS_RETURN) = 3;
882 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
885 // viewpos isn't in any PVS... darn
886 PRVM_G_FLOAT(OFS_RETURN) = 2;
889 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
898 Sends text over to the client's execution buffer
900 stuffcmd (clientent, value, ...)
903 static void VM_SV_stuffcmd (void)
907 char string[VM_STRINGTEMP_LENGTH];
909 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
911 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
912 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
914 VM_Warning("Can't stuffcmd to a non-client\n");
918 VM_VarString(1, string, sizeof(string));
921 host_client = svs.clients + entnum-1;
922 Host_ClientCommands ("%s", string);
930 Returns a chain of entities that have origins within a spherical area
932 findradius (origin, radius)
935 static void VM_SV_findradius (void)
937 prvm_edict_t *ent, *chain;
938 vec_t radius, radius2;
939 vec3_t org, eorg, mins, maxs;
942 static prvm_edict_t *touchedicts[MAX_EDICTS];
945 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
948 chainfield = PRVM_G_INT(OFS_PARM2);
950 chainfield = prog->fieldoffsets.chain;
952 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
954 chain = (prvm_edict_t *)prog->edicts;
956 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
957 radius = PRVM_G_FLOAT(OFS_PARM1);
958 radius2 = radius * radius;
960 mins[0] = org[0] - (radius + 1);
961 mins[1] = org[1] - (radius + 1);
962 mins[2] = org[2] - (radius + 1);
963 maxs[0] = org[0] + (radius + 1);
964 maxs[1] = org[1] + (radius + 1);
965 maxs[2] = org[2] + (radius + 1);
966 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
967 if (numtouchedicts > MAX_EDICTS)
969 // this never happens
970 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
971 numtouchedicts = MAX_EDICTS;
973 for (i = 0;i < numtouchedicts;i++)
975 ent = touchedicts[i];
976 prog->xfunction->builtinsprofile++;
977 // Quake did not return non-solid entities but darkplaces does
978 // (note: this is the reason you can't blow up fallen zombies)
979 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
981 // LordHavoc: compare against bounding box rather than center so it
982 // doesn't miss large objects, and use DotProduct instead of Length
983 // for a major speedup
984 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
985 if (sv_gameplayfix_findradiusdistancetobox.integer)
987 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
988 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
989 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
992 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
993 if (DotProduct(eorg, eorg) < radius2)
995 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1000 VM_RETURN_EDICT(chain);
1003 static void VM_SV_precache_sound (void)
1005 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1006 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1009 static void VM_SV_precache_model (void)
1011 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1012 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1013 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1020 float(float yaw, float dist[, settrace]) walkmove
1023 static void VM_SV_walkmove (void)
1032 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1034 // assume failure if it returns early
1035 PRVM_G_FLOAT(OFS_RETURN) = 0;
1037 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1038 if (ent == prog->edicts)
1040 VM_Warning("walkmove: can not modify world entity\n");
1043 if (ent->priv.server->free)
1045 VM_Warning("walkmove: can not modify free entity\n");
1048 yaw = PRVM_G_FLOAT(OFS_PARM0);
1049 dist = PRVM_G_FLOAT(OFS_PARM1);
1050 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1052 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1055 yaw = yaw*M_PI*2 / 360;
1057 move[0] = cos(yaw)*dist;
1058 move[1] = sin(yaw)*dist;
1061 // save program state, because SV_movestep may call other progs
1062 oldf = prog->xfunction;
1063 oldself = PRVM_serverglobaledict(self);
1065 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1068 // restore program state
1069 prog->xfunction = oldf;
1070 PRVM_serverglobaledict(self) = oldself;
1080 static void VM_SV_droptofloor (void)
1086 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1088 // assume failure if it returns early
1089 PRVM_G_FLOAT(OFS_RETURN) = 0;
1091 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1092 if (ent == prog->edicts)
1094 VM_Warning("droptofloor: can not modify world entity\n");
1097 if (ent->priv.server->free)
1099 VM_Warning("droptofloor: can not modify free entity\n");
1103 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1106 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1107 SV_UnstickEntity(ent);
1109 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1110 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1113 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]);
1114 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1115 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1116 VectorSubtract(trace.endpos, offset, trace.endpos);
1117 if (trace.startsolid)
1119 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]);
1120 SV_UnstickEntity(ent);
1122 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1123 PRVM_serveredictedict(ent, groundentity) = 0;
1124 PRVM_G_FLOAT(OFS_RETURN) = 1;
1126 else if (trace.fraction < 1)
1128 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]);
1129 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1130 SV_UnstickEntity(ent);
1132 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1133 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1134 PRVM_G_FLOAT(OFS_RETURN) = 1;
1135 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1136 ent->priv.server->suspendedinairflag = true;
1141 if (trace.fraction != 1)
1143 if (trace.fraction < 1)
1144 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1146 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1147 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1148 PRVM_G_FLOAT(OFS_RETURN) = 1;
1149 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1150 ent->priv.server->suspendedinairflag = true;
1159 void(float style, string value) lightstyle
1162 static void VM_SV_lightstyle (void)
1169 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1171 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1172 val = PRVM_G_STRING(OFS_PARM1);
1174 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1175 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1178 // change the string in sv
1179 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1181 // send message to all clients on this server
1182 if (sv.state != ss_active)
1185 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1187 if (client->active && client->netconnection)
1189 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1190 MSG_WriteChar (&client->netconnection->message,style);
1191 MSG_WriteString (&client->netconnection->message, val);
1201 static void VM_SV_checkbottom (void)
1203 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1204 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1212 static void VM_SV_pointcontents (void)
1214 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1215 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1222 Pick a vector for the player to shoot along
1223 vector aim(entity, missilespeed)
1226 static void VM_SV_aim (void)
1228 prvm_edict_t *ent, *check, *bestent;
1229 vec3_t start, dir, end, bestdir;
1232 float dist, bestdist;
1235 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1237 // assume failure if it returns early
1238 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1239 // if sv_aim is so high it can't possibly accept anything, skip out early
1240 if (sv_aim.value >= 1)
1243 ent = PRVM_G_EDICT(OFS_PARM0);
1244 if (ent == prog->edicts)
1246 VM_Warning("aim: can not use world entity\n");
1249 if (ent->priv.server->free)
1251 VM_Warning("aim: can not use free entity\n");
1254 //speed = PRVM_G_FLOAT(OFS_PARM1);
1256 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1259 // try sending a trace straight
1260 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1261 VectorMA (start, 2048, dir, end);
1262 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1263 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1264 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1266 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1271 // try all possible entities
1272 VectorCopy (dir, bestdir);
1273 bestdist = sv_aim.value;
1276 check = PRVM_NEXT_EDICT(prog->edicts);
1277 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1279 prog->xfunction->builtinsprofile++;
1280 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1284 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1285 continue; // don't aim at teammate
1286 for (j=0 ; j<3 ; j++)
1287 end[j] = PRVM_serveredictvector(check, origin)[j]
1288 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1289 VectorSubtract (end, start, dir);
1290 VectorNormalize (dir);
1291 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1292 if (dist < bestdist)
1293 continue; // to far to turn
1294 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1295 if (tr.ent == check)
1296 { // can shoot at this one
1304 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1305 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1306 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1308 VectorNormalize (end);
1309 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1313 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1318 ===============================================================================
1322 ===============================================================================
1325 #define MSG_BROADCAST 0 // unreliable to all
1326 #define MSG_ONE 1 // reliable to one (msg_entity)
1327 #define MSG_ALL 2 // reliable to all
1328 #define MSG_INIT 3 // write to the init string
1329 #define MSG_ENTITY 5
1331 sizebuf_t *WriteDest (void)
1337 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1341 return &sv.datagram;
1344 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1345 entnum = PRVM_NUM_FOR_EDICT(ent);
1346 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1348 VM_Warning ("WriteDest: tried to write to non-client\n");
1349 return &sv.reliable_datagram;
1352 return &svs.clients[entnum-1].netconnection->message;
1355 VM_Warning ("WriteDest: bad destination\n");
1357 return &sv.reliable_datagram;
1363 return sv.writeentitiestoclient_msg;
1369 static void VM_SV_WriteByte (void)
1371 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1372 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1375 static void VM_SV_WriteChar (void)
1377 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1378 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1381 static void VM_SV_WriteShort (void)
1383 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1384 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1387 static void VM_SV_WriteLong (void)
1389 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1390 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1393 static void VM_SV_WriteAngle (void)
1395 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1396 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1399 static void VM_SV_WriteCoord (void)
1401 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1402 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1405 static void VM_SV_WriteString (void)
1407 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1408 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1411 static void VM_SV_WriteUnterminatedString (void)
1413 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1414 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1418 static void VM_SV_WriteEntity (void)
1420 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1421 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1424 // writes a picture as at most size bytes of data
1426 // IMGNAME \0 SIZE(short) IMGDATA
1427 // if failed to read/compress:
1429 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1430 static void VM_SV_WritePicture (void)
1432 const char *imgname;
1436 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1438 imgname = PRVM_G_STRING(OFS_PARM1);
1439 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1443 MSG_WriteString(WriteDest(), imgname);
1444 if(Image_Compress(imgname, size, &buf, &size))
1447 MSG_WriteShort(WriteDest(), size);
1448 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1453 MSG_WriteShort(WriteDest(), 0);
1457 //////////////////////////////////////////////////////////
1459 static void VM_SV_makestatic (void)
1464 // allow 0 parameters due to an id1 qc bug in which this function is used
1465 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1466 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1468 if (prog->argc >= 1)
1469 ent = PRVM_G_EDICT(OFS_PARM0);
1471 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1472 if (ent == prog->edicts)
1474 VM_Warning("makestatic: can not modify world entity\n");
1477 if (ent->priv.server->free)
1479 VM_Warning("makestatic: can not modify free entity\n");
1484 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1489 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1490 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1491 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1493 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1495 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1496 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1497 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1501 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1502 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1503 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1506 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1507 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1508 for (i=0 ; i<3 ; i++)
1510 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1511 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1514 // throw the entity away now
1518 //=============================================================================
1525 static void VM_SV_setspawnparms (void)
1531 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1533 ent = PRVM_G_EDICT(OFS_PARM0);
1534 i = PRVM_NUM_FOR_EDICT(ent);
1535 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1537 Con_Print("tried to setspawnparms on a non-client\n");
1541 // copy spawn parms out of the client_t
1542 client = svs.clients + i-1;
1543 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1544 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1551 Returns a color vector indicating the lighting at the requested point.
1553 (Internal Operation note: actually measures the light beneath the point, just like
1554 the model lighting on the client)
1559 static void VM_SV_getlight (void)
1561 vec3_t ambientcolor, diffusecolor, diffusenormal;
1563 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1564 p = PRVM_G_VECTOR(OFS_PARM0);
1565 VectorClear(ambientcolor);
1566 VectorClear(diffusecolor);
1567 VectorClear(diffusenormal);
1568 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1569 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1570 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1575 unsigned char type; // 1/2/8 or other value if isn't used
1579 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1580 static int vm_customstats_last;
1582 void VM_CustomStats_Clear (void)
1586 Z_Free(vm_customstats);
1587 vm_customstats = NULL;
1588 vm_customstats_last = -1;
1592 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1600 for(i=0; i<vm_customstats_last+1 ;i++)
1602 if(!vm_customstats[i].type)
1604 switch(vm_customstats[i].type)
1606 //string as 16 bytes
1609 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1610 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1611 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1612 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1613 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1615 //float field sent as-is
1617 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1619 //integer value of float field
1621 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1629 // void(float index, float type, .void field) SV_AddStat = #232;
1630 // Set up an auto-sent player stat.
1631 // Client's get thier own fields sent to them. Index may not be less than 32.
1632 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1633 // 1: string (4 stats carrying a total of 16 charactures)
1634 // 2: float (one stat, float converted to an integer for transportation)
1635 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1636 static void VM_SV_AddStat (void)
1641 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1645 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1648 VM_Warning("PF_SV_AddStat: not enough memory\n");
1652 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1653 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1654 off = PRVM_G_INT (OFS_PARM2);
1659 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1662 if(i >= (MAX_CL_STATS-32))
1664 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1667 if(i > (MAX_CL_STATS-32-4) && type == 1)
1669 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1672 vm_customstats[i].type = type;
1673 vm_customstats[i].fieldoffset = off;
1674 if(vm_customstats_last < i)
1675 vm_customstats_last = i;
1682 copies data from one entity to another
1684 copyentity(src, dst)
1687 static void VM_SV_copyentity (void)
1689 prvm_edict_t *in, *out;
1690 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1691 in = PRVM_G_EDICT(OFS_PARM0);
1692 if (in == prog->edicts)
1694 VM_Warning("copyentity: can not read world entity\n");
1697 if (in->priv.server->free)
1699 VM_Warning("copyentity: can not read free entity\n");
1702 out = PRVM_G_EDICT(OFS_PARM1);
1703 if (out == prog->edicts)
1705 VM_Warning("copyentity: can not modify world entity\n");
1708 if (out->priv.server->free)
1710 VM_Warning("copyentity: can not modify free entity\n");
1713 memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
1722 sets the color of a client and broadcasts the update to all connected clients
1724 setcolor(clientent, value)
1727 static void VM_SV_setcolor (void)
1732 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1733 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1734 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1736 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1738 Con_Print("tried to setcolor a non-client\n");
1742 client = svs.clients + entnum-1;
1745 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1746 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1749 if (client->old_colors != client->colors)
1751 client->old_colors = client->colors;
1752 // send notification to all clients
1753 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1754 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1755 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1763 effect(origin, modelname, startframe, framecount, framerate)
1766 static void VM_SV_effect (void)
1770 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1771 s = PRVM_G_STRING(OFS_PARM1);
1774 VM_Warning("effect: no model specified\n");
1778 i = SV_ModelIndex(s, 1);
1781 VM_Warning("effect: model not precached\n");
1785 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1787 VM_Warning("effect: framecount < 1\n");
1791 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1793 VM_Warning("effect: framerate < 1\n");
1797 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));
1800 static void VM_SV_te_blood (void)
1802 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1803 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1805 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1806 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1808 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1809 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1810 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1812 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1813 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1814 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1816 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1817 SV_FlushBroadcastMessages();
1820 static void VM_SV_te_bloodshower (void)
1822 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1823 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1825 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1826 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1828 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1830 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1832 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1833 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1834 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1836 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1838 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1839 SV_FlushBroadcastMessages();
1842 static void VM_SV_te_explosionrgb (void)
1844 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1845 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1846 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1848 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1849 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1850 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1852 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1853 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1854 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1855 SV_FlushBroadcastMessages();
1858 static void VM_SV_te_particlecube (void)
1860 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1861 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1863 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1864 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1866 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1868 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1870 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1874 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1875 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1876 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1878 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1880 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1881 // gravity true/false
1882 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1884 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1885 SV_FlushBroadcastMessages();
1888 static void VM_SV_te_particlerain (void)
1890 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1891 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1893 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1894 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1896 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1900 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1908 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1910 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1911 SV_FlushBroadcastMessages();
1914 static void VM_SV_te_particlesnow (void)
1916 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1917 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1919 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1920 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1922 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1923 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1924 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1926 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1934 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1936 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1937 SV_FlushBroadcastMessages();
1940 static void VM_SV_te_spark (void)
1942 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1943 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1945 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1946 MSG_WriteByte(&sv.datagram, TE_SPARK);
1948 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1949 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1950 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1952 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1953 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1954 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1956 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1957 SV_FlushBroadcastMessages();
1960 static void VM_SV_te_gunshotquad (void)
1962 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1963 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1964 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1969 SV_FlushBroadcastMessages();
1972 static void VM_SV_te_spikequad (void)
1974 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1975 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1976 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1978 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1979 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1980 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1981 SV_FlushBroadcastMessages();
1984 static void VM_SV_te_superspikequad (void)
1986 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1987 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1988 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1990 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1991 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1992 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1993 SV_FlushBroadcastMessages();
1996 static void VM_SV_te_explosionquad (void)
1998 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
1999 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2000 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2002 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2004 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2005 SV_FlushBroadcastMessages();
2008 static void VM_SV_te_smallflash (void)
2010 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2011 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2012 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2014 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2015 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2016 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2017 SV_FlushBroadcastMessages();
2020 static void VM_SV_te_customflash (void)
2022 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2023 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2025 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2026 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2028 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2029 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2030 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2032 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2034 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2036 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2037 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2038 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2039 SV_FlushBroadcastMessages();
2042 static void VM_SV_te_gunshot (void)
2044 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2045 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2046 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2048 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2049 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2050 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2051 SV_FlushBroadcastMessages();
2054 static void VM_SV_te_spike (void)
2056 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2057 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2058 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2060 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2061 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2062 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2063 SV_FlushBroadcastMessages();
2066 static void VM_SV_te_superspike (void)
2068 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2069 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2070 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2072 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2074 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2075 SV_FlushBroadcastMessages();
2078 static void VM_SV_te_explosion (void)
2080 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2081 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2082 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2084 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2085 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2086 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2087 SV_FlushBroadcastMessages();
2090 static void VM_SV_te_tarexplosion (void)
2092 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2093 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2094 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2096 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2097 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2098 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2099 SV_FlushBroadcastMessages();
2102 static void VM_SV_te_wizspike (void)
2104 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2105 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2106 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2108 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2109 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2110 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2111 SV_FlushBroadcastMessages();
2114 static void VM_SV_te_knightspike (void)
2116 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2117 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2118 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2120 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2121 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2122 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2123 SV_FlushBroadcastMessages();
2126 static void VM_SV_te_lavasplash (void)
2128 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2129 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2130 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2132 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2133 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2134 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2135 SV_FlushBroadcastMessages();
2138 static void VM_SV_te_teleport (void)
2140 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2141 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2142 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2144 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2145 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2146 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2147 SV_FlushBroadcastMessages();
2150 static void VM_SV_te_explosion2 (void)
2152 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2153 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2154 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2156 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2157 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2158 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2160 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2161 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2162 SV_FlushBroadcastMessages();
2165 static void VM_SV_te_lightning1 (void)
2167 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2168 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2169 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2171 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2173 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2174 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2175 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2177 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2178 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2179 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2180 SV_FlushBroadcastMessages();
2183 static void VM_SV_te_lightning2 (void)
2185 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2186 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2187 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2189 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2191 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2192 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2193 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2195 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2196 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2197 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2198 SV_FlushBroadcastMessages();
2201 static void VM_SV_te_lightning3 (void)
2203 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2204 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2205 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2207 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2209 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2210 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2211 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2213 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2214 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2215 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2216 SV_FlushBroadcastMessages();
2219 static void VM_SV_te_beam (void)
2221 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2222 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2223 MSG_WriteByte(&sv.datagram, TE_BEAM);
2225 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2227 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2231 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2232 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2234 SV_FlushBroadcastMessages();
2237 static void VM_SV_te_plasmaburn (void)
2239 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2240 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2241 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2242 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2243 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2244 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2245 SV_FlushBroadcastMessages();
2248 static void VM_SV_te_flamejet (void)
2250 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2251 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2252 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2254 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2255 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2256 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2258 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2259 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2260 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2262 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2263 SV_FlushBroadcastMessages();
2266 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2267 //this function originally written by KrimZon, made shorter by LordHavoc
2268 static void VM_SV_clientcommand (void)
2270 client_t *temp_client;
2272 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2274 //find client for this entity
2275 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2276 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2278 Con_Print("PF_clientcommand: entity is not a client\n");
2282 temp_client = host_client;
2283 host_client = svs.clients + i;
2284 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2285 host_client = temp_client;
2288 //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)
2289 static void VM_SV_setattachment (void)
2291 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2292 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2293 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2296 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2298 if (e == prog->edicts)
2300 VM_Warning("setattachment: can not modify world entity\n");
2303 if (e->priv.server->free)
2305 VM_Warning("setattachment: can not modify free entity\n");
2309 if (tagentity == NULL)
2310 tagentity = prog->edicts;
2314 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2316 model = SV_GetModelFromEdict(tagentity);
2319 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2321 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);
2324 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));
2327 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2328 PRVM_serveredictfloat(e, tag_index) = tagindex;
2331 /////////////////////////////////////////
2332 // DP_MD3_TAGINFO extension coded by VorteX
2334 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2338 i = (int)PRVM_serveredictfloat(e, modelindex);
2339 if (i < 1 || i >= MAX_MODELS)
2342 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2345 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2352 Matrix4x4_CreateIdentity(tag_localmatrix);
2354 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2356 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2367 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2370 float pitchsign = 1;
2372 scale = PRVM_serveredictfloat(ent, scale);
2377 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);
2380 pitchsign = SV_GetPitchSign(ent);
2381 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);
2385 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2388 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2390 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2391 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2392 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2393 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2395 *out = identitymatrix;
2399 // Warnings/errors code:
2400 // 0 - normal (everything all-right)
2403 // 3 - null or non-precached model
2404 // 4 - no tags with requested index
2405 // 5 - runaway loop at attachment chain
2406 extern cvar_t cl_bob;
2407 extern cvar_t cl_bobcycle;
2408 extern cvar_t cl_bobup;
2409 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2412 int modelindex, attachloop;
2413 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2416 *out = identitymatrix; // warnings and errors return identical matrix
2418 if (ent == prog->edicts)
2420 if (ent->priv.server->free)
2423 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2424 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2427 model = SV_GetModelByIndex(modelindex);
2429 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2430 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2431 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2433 tagmatrix = identitymatrix;
2434 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2438 if (attachloop >= 256) // prevent runaway looping
2440 // apply transformation by child's tagindex on parent entity and then
2441 // by parent entity itself
2442 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2443 if (ret && attachloop == 0)
2445 SV_GetEntityMatrix(ent, &entitymatrix, false);
2446 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2447 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2448 // next iteration we process the parent entity
2449 if (PRVM_serveredictedict(ent, tag_entity))
2451 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2452 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2459 // RENDER_VIEWMODEL magic
2460 if (PRVM_serveredictedict(ent, viewmodelforclient))
2462 Matrix4x4_Copy(&tagmatrix, out);
2463 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2465 SV_GetEntityMatrix(ent, &entitymatrix, true);
2466 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2469 // Cl_bob, ported from rendering code
2470 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2473 // LordHavoc: this code is *weird*, but not replacable (I think it
2474 // should be done in QC on the server, but oh well, quake is quake)
2475 // LordHavoc: figured out bobup: the time at which the sin is at 180
2476 // degrees (which allows lengthening or squishing the peak or valley)
2477 cycle = sv.time/cl_bobcycle.value;
2478 cycle -= (int)cycle;
2479 if (cycle < cl_bobup.value)
2480 cycle = sin(M_PI * cycle / cl_bobup.value);
2482 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2483 // bob is proportional to velocity in the xy plane
2484 // (don't count Z, or jumping messes it up)
2485 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;
2486 bob = bob*0.3 + bob*0.7*cycle;
2487 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2494 //float(entity ent, string tagname) gettagindex;
2496 static void VM_SV_gettagindex (void)
2499 const char *tag_name;
2502 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2504 ent = PRVM_G_EDICT(OFS_PARM0);
2505 tag_name = PRVM_G_STRING(OFS_PARM1);
2507 if (ent == prog->edicts)
2509 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2512 if (ent->priv.server->free)
2514 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2519 if (!SV_GetModelFromEdict(ent))
2520 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2523 tag_index = SV_GetTagIndex(ent, tag_name);
2525 if(developer_extra.integer)
2526 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2528 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2531 //vector(entity ent, float tagindex) gettaginfo;
2532 static void VM_SV_gettaginfo (void)
2536 matrix4x4_t tag_matrix;
2537 matrix4x4_t tag_localmatrix;
2539 const char *tagname;
2541 vec3_t fo, le, up, trans;
2542 const dp_model_t *model;
2544 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2546 e = PRVM_G_EDICT(OFS_PARM0);
2547 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2549 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2550 Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
2551 VectorScale(le, -1, PRVM_serverglobalvector(v_right));
2552 model = SV_GetModelFromEdict(e);
2553 VM_GenerateFrameGroupBlend(e->priv.server->framegroupblend, e);
2554 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
2555 VM_UpdateEdictSkeleton(e, model, e->priv.server->frameblend);
2556 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2557 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2559 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2560 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(tagname) : 0;
2561 VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
2562 VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
2563 VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
2564 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2569 VM_Warning("gettagindex: can't affect world entity\n");
2572 VM_Warning("gettagindex: can't affect free entity\n");
2575 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2578 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2581 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2586 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2587 static void VM_SV_dropclient (void)
2590 client_t *oldhostclient;
2591 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2592 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2593 if (clientnum < 0 || clientnum >= svs.maxclients)
2595 VM_Warning("dropclient: not a client\n");
2598 if (!svs.clients[clientnum].active)
2600 VM_Warning("dropclient: that client slot is not connected\n");
2603 oldhostclient = host_client;
2604 host_client = svs.clients + clientnum;
2605 SV_DropClient(false);
2606 host_client = oldhostclient;
2609 //entity() spawnclient (DP_SV_BOTCLIENT)
2610 static void VM_SV_spawnclient (void)
2614 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2615 prog->xfunction->builtinsprofile += 2;
2617 for (i = 0;i < svs.maxclients;i++)
2619 if (!svs.clients[i].active)
2621 prog->xfunction->builtinsprofile += 100;
2622 SV_ConnectClient (i, NULL);
2623 // this has to be set or else ClientDisconnect won't be called
2624 // we assume the qc will call ClientConnect...
2625 svs.clients[i].clientconnectcalled = true;
2626 ed = PRVM_EDICT_NUM(i + 1);
2630 VM_RETURN_EDICT(ed);
2633 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2634 static void VM_SV_clienttype (void)
2637 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2638 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2639 if (clientnum < 0 || clientnum >= svs.maxclients)
2640 PRVM_G_FLOAT(OFS_RETURN) = 3;
2641 else if (!svs.clients[clientnum].active)
2642 PRVM_G_FLOAT(OFS_RETURN) = 0;
2643 else if (svs.clients[clientnum].netconnection)
2644 PRVM_G_FLOAT(OFS_RETURN) = 1;
2646 PRVM_G_FLOAT(OFS_RETURN) = 2;
2653 string(string key) serverkey
2656 void VM_SV_serverkey(void)
2658 char string[VM_STRINGTEMP_LENGTH];
2659 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2660 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2661 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2664 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2665 static void VM_SV_setmodelindex (void)
2670 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2672 e = PRVM_G_EDICT(OFS_PARM0);
2673 if (e == prog->edicts)
2675 VM_Warning("setmodelindex: can not modify world entity\n");
2678 if (e->priv.server->free)
2680 VM_Warning("setmodelindex: can not modify free entity\n");
2683 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2684 if (i <= 0 || i >= MAX_MODELS)
2686 VM_Warning("setmodelindex: invalid modelindex\n");
2689 if (!sv.model_precache[i][0])
2691 VM_Warning("setmodelindex: model not precached\n");
2695 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
2696 PRVM_serveredictfloat(e, modelindex) = i;
2698 mod = SV_GetModelByIndex(i);
2702 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2703 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2705 SetMinMaxSize (e, quakemins, quakemaxs, true);
2708 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2711 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2712 static void VM_SV_modelnameforindex (void)
2715 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2717 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2719 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2720 if (i <= 0 || i >= MAX_MODELS)
2722 VM_Warning("modelnameforindex: invalid modelindex\n");
2725 if (!sv.model_precache[i][0])
2727 VM_Warning("modelnameforindex: model not precached\n");
2731 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2734 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2735 static void VM_SV_particleeffectnum (void)
2738 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2739 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2742 PRVM_G_FLOAT(OFS_RETURN) = i;
2745 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2746 static void VM_SV_trailparticles (void)
2748 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2750 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2753 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2754 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2755 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2756 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2757 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2758 SV_FlushBroadcastMessages();
2761 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2762 static void VM_SV_pointparticles (void)
2764 int effectnum, count;
2766 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2768 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2771 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2772 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2773 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2774 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2775 if (count == 1 && !VectorLength2(vel))
2778 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2779 MSG_WriteShort(&sv.datagram, effectnum);
2780 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2784 // 1+2+12+12+2=29 bytes
2785 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2786 MSG_WriteShort(&sv.datagram, effectnum);
2787 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2788 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2789 MSG_WriteShort(&sv.datagram, count);
2792 SV_FlushBroadcastMessages();
2795 //PF_setpause, // void(float pause) setpause = #531;
2796 static void VM_SV_setpause(void) {
2798 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2799 if (pauseValue != 0) { //pause the game
2801 sv.pausedstart = Sys_DoubleTime();
2802 } else { //disable pause, in case it was enabled
2803 if (sv.paused != 0) {
2808 // send notification to all clients
2809 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2810 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2813 // #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.
2814 static void VM_SV_skel_create(void)
2816 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2817 dp_model_t *model = SV_GetModelByIndex(modelindex);
2818 skeleton_t *skeleton;
2820 PRVM_G_FLOAT(OFS_RETURN) = 0;
2821 if (!model || !model->num_bones)
2823 for (i = 0;i < MAX_EDICTS;i++)
2824 if (!prog->skeletons[i])
2826 if (i == MAX_EDICTS)
2828 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2829 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2830 skeleton->model = model;
2831 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2832 // initialize to identity matrices
2833 for (i = 0;i < skeleton->model->num_bones;i++)
2834 skeleton->relativetransforms[i] = identitymatrix;
2837 // #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
2838 static void VM_SV_skel_build(void)
2840 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2841 skeleton_t *skeleton;
2842 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2843 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2844 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2845 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2846 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2847 dp_model_t *model = SV_GetModelByIndex(modelindex);
2852 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2853 frameblend_t frameblend[MAX_FRAMEBLENDS];
2854 matrix4x4_t blendedmatrix;
2856 PRVM_G_FLOAT(OFS_RETURN) = 0;
2857 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2859 firstbone = max(0, firstbone);
2860 lastbone = min(lastbone, model->num_bones - 1);
2861 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2862 VM_GenerateFrameGroupBlend(framegroupblend, ed);
2863 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
2864 blendfrac = 1.0f - retainfrac;
2865 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2866 frameblend[numblends].lerp *= blendfrac;
2867 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2869 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2870 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2871 for (blendindex = 0;blendindex < numblends;blendindex++)
2873 Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2874 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2876 skeleton->relativetransforms[bonenum] = blendedmatrix;
2878 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2881 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2882 static void VM_SV_skel_get_numbones(void)
2884 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2885 skeleton_t *skeleton;
2886 PRVM_G_FLOAT(OFS_RETURN) = 0;
2887 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2889 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2892 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2893 static void VM_SV_skel_get_bonename(void)
2895 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2896 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2897 skeleton_t *skeleton;
2898 PRVM_G_INT(OFS_RETURN) = 0;
2899 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2901 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2903 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(skeleton->model->data_bones[bonenum].name);
2906 // #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)
2907 static void VM_SV_skel_get_boneparent(void)
2909 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2910 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2911 skeleton_t *skeleton;
2912 PRVM_G_FLOAT(OFS_RETURN) = 0;
2913 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2915 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2917 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2920 // #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
2921 static void VM_SV_skel_find_bone(void)
2923 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2924 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2925 skeleton_t *skeleton;
2926 PRVM_G_FLOAT(OFS_RETURN) = 0;
2927 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2929 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2932 // #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)
2933 static void VM_SV_skel_get_bonerel(void)
2935 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2936 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2937 skeleton_t *skeleton;
2939 vec3_t forward, left, up, origin;
2940 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2941 VectorClear(PRVM_clientglobalvector(v_forward));
2942 VectorClear(PRVM_clientglobalvector(v_right));
2943 VectorClear(PRVM_clientglobalvector(v_up));
2944 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2946 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2948 matrix = skeleton->relativetransforms[bonenum];
2949 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2950 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2951 VectorNegate(left, PRVM_clientglobalvector(v_right));
2952 VectorCopy(up, PRVM_clientglobalvector(v_up));
2953 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2956 // #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)
2957 static void VM_SV_skel_get_boneabs(void)
2959 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2960 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2961 skeleton_t *skeleton;
2964 vec3_t forward, left, up, origin;
2965 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2966 VectorClear(PRVM_clientglobalvector(v_forward));
2967 VectorClear(PRVM_clientglobalvector(v_right));
2968 VectorClear(PRVM_clientglobalvector(v_up));
2969 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2971 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2973 matrix = skeleton->relativetransforms[bonenum];
2974 // convert to absolute
2975 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
2978 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
2980 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2981 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2982 VectorNegate(left, PRVM_clientglobalvector(v_right));
2983 VectorCopy(up, PRVM_clientglobalvector(v_up));
2984 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2987 // #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)
2988 static void VM_SV_skel_set_bone(void)
2990 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2991 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2992 vec3_t forward, left, up, origin;
2993 skeleton_t *skeleton;
2995 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2997 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2999 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3000 VectorNegate(PRVM_clientglobalvector(v_right), left);
3001 VectorCopy(PRVM_clientglobalvector(v_up), up);
3002 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3003 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3004 skeleton->relativetransforms[bonenum] = matrix;
3007 // #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)
3008 static void VM_SV_skel_mul_bone(void)
3010 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3011 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3012 vec3_t forward, left, up, origin;
3013 skeleton_t *skeleton;
3016 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3018 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3020 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3021 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3022 VectorNegate(PRVM_clientglobalvector(v_right), left);
3023 VectorCopy(PRVM_clientglobalvector(v_up), up);
3024 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3025 temp = skeleton->relativetransforms[bonenum];
3026 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3029 // #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)
3030 static void VM_SV_skel_mul_bones(void)
3032 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3033 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3034 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3036 vec3_t forward, left, up, origin;
3037 skeleton_t *skeleton;
3040 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3042 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3043 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3044 VectorNegate(PRVM_clientglobalvector(v_right), left);
3045 VectorCopy(PRVM_clientglobalvector(v_up), up);
3046 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3047 firstbone = max(0, firstbone);
3048 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3049 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3051 temp = skeleton->relativetransforms[bonenum];
3052 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3056 // #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
3057 static void VM_SV_skel_copybones(void)
3059 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3060 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3061 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3062 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3064 skeleton_t *skeletondst;
3065 skeleton_t *skeletonsrc;
3066 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3068 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3070 firstbone = max(0, firstbone);
3071 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3072 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3073 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3074 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3077 // #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)
3078 static void VM_SV_skel_delete(void)
3080 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3081 skeleton_t *skeleton;
3082 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3085 prog->skeletons[skeletonindex] = NULL;
3088 // #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
3089 static void VM_SV_frameforname(void)
3091 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3092 dp_model_t *model = SV_GetModelByIndex(modelindex);
3093 const char *name = PRVM_G_STRING(OFS_PARM1);
3095 PRVM_G_FLOAT(OFS_RETURN) = -1;
3096 if (!model || !model->animscenes)
3098 for (i = 0;i < model->numframes;i++)
3100 if (!strcasecmp(model->animscenes[i].name, name))
3102 PRVM_G_FLOAT(OFS_RETURN) = i;
3108 // #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.
3109 static void VM_SV_frameduration(void)
3111 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3112 dp_model_t *model = SV_GetModelByIndex(modelindex);
3113 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3114 PRVM_G_FLOAT(OFS_RETURN) = 0;
3115 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3117 if (model->animscenes[framenum].framerate)
3118 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3122 prvm_builtin_t vm_sv_builtins[] = {
3123 NULL, // #0 NULL function (not callable) (QUAKE)
3124 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3125 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3126 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3127 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3128 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3129 VM_break, // #6 void() break (QUAKE)
3130 VM_random, // #7 float() random (QUAKE)
3131 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3132 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3133 VM_error, // #10 void(string e) error (QUAKE)
3134 VM_objerror, // #11 void(string e) objerror (QUAKE)
3135 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3136 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3137 VM_spawn, // #14 entity() spawn (QUAKE)
3138 VM_remove, // #15 void(entity e) remove (QUAKE)
3139 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3140 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3141 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3142 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3143 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3144 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3145 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3146 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3147 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3148 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3149 VM_ftos, // #26 string(float f) ftos (QUAKE)
3150 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3151 VM_coredump, // #28 void() coredump (QUAKE)
3152 VM_traceon, // #29 void() traceon (QUAKE)
3153 VM_traceoff, // #30 void() traceoff (QUAKE)
3154 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3155 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3156 NULL, // #33 (QUAKE)
3157 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3158 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3159 VM_rint, // #36 float(float v) rint (QUAKE)
3160 VM_floor, // #37 float(float v) floor (QUAKE)
3161 VM_ceil, // #38 float(float v) ceil (QUAKE)
3162 NULL, // #39 (QUAKE)
3163 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3164 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3165 NULL, // #42 (QUAKE)
3166 VM_fabs, // #43 float(float f) fabs (QUAKE)
3167 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3168 VM_cvar, // #45 float(string s) cvar (QUAKE)
3169 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3170 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3171 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3172 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3173 NULL, // #50 (QUAKE)
3174 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3175 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3176 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3177 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3178 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3179 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3180 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3181 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3182 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3183 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3184 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3185 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3186 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3187 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3188 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3189 NULL, // #66 (QUAKE)
3190 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3191 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3192 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3193 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3194 NULL, // #71 (QUAKE)
3195 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3196 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3197 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3198 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3199 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3200 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3201 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3202 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3203 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3204 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3205 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3206 NULL, // #83 (QUAKE)
3207 NULL, // #84 (QUAKE)
3208 NULL, // #85 (QUAKE)
3209 NULL, // #86 (QUAKE)
3210 NULL, // #87 (QUAKE)
3211 NULL, // #88 (QUAKE)
3212 NULL, // #89 (QUAKE)
3213 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3214 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3215 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3216 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3217 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3218 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3219 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3220 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3221 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3222 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3223 // FrikaC and Telejano range #100-#199
3234 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3235 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3236 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3237 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3238 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3239 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3240 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3241 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3242 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3243 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3324 // FTEQW range #200-#299
3343 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3346 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3347 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3348 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3349 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3350 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3351 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3352 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3353 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3354 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3355 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3357 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3365 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3388 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.
3389 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
3390 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3391 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3392 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)
3393 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
3394 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)
3395 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)
3396 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)
3397 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)
3398 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)
3399 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
3400 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)
3401 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
3402 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.
3425 // CSQC range #300-#399
3426 NULL, // #300 void() clearscene (EXT_CSQC)
3427 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3428 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3429 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3430 NULL, // #304 void() renderscene (EXT_CSQC)
3431 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3432 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3433 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3434 NULL, // #308 void() R_EndPolygon
3436 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3437 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3441 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3442 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3443 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3444 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3445 NULL, // #319 void(string name) freepic (EXT_CSQC)
3446 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3447 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3448 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3449 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3450 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3451 NULL, // #325 void(void) drawresetcliparea
3456 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3457 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3458 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3459 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3460 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3461 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3462 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3463 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3464 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3465 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3466 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3467 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3468 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3469 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3470 NULL, // #344 vector() getmousepos (EXT_CSQC)
3471 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3472 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3473 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3474 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3475 NULL, // #349 float() isdemo (EXT_CSQC)
3476 VM_isserver, // #350 float() isserver (EXT_CSQC)
3477 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3478 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3479 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3480 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3486 NULL, // #360 float() readbyte (EXT_CSQC)
3487 NULL, // #361 float() readchar (EXT_CSQC)
3488 NULL, // #362 float() readshort (EXT_CSQC)
3489 NULL, // #363 float() readlong (EXT_CSQC)
3490 NULL, // #364 float() readcoord (EXT_CSQC)
3491 NULL, // #365 float() readangle (EXT_CSQC)
3492 NULL, // #366 string() readstring (EXT_CSQC)
3493 NULL, // #367 float() readfloat (EXT_CSQC)
3526 // LordHavoc's range #400-#499
3527 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3528 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3529 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3530 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3531 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3532 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3533 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3534 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3535 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)
3536 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3537 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3538 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3539 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3540 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3541 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3542 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3543 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3544 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3545 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3546 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3547 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3548 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3549 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3550 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3551 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3552 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3553 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3554 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3555 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3556 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3557 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3558 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3559 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3560 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3561 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3562 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3563 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3564 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3565 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3566 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3567 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3568 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3569 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3570 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3571 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3572 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3573 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3574 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3575 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3576 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3577 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3578 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3579 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3580 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3581 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3582 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3583 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3584 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3586 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3587 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3588 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3589 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3590 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3591 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3592 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3593 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3594 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3595 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3596 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3598 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3599 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3600 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3601 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3602 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3603 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3604 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3605 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3606 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3607 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3608 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3609 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3610 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3611 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3612 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3613 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3621 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3622 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3623 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3624 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3625 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3626 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3627 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3628 VM_SV_WritePicture, // #501
3630 VM_whichpack, // #503 string(string) whichpack = #503;
3637 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3638 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3639 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3640 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)
3641 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3642 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3643 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3644 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3645 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3646 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3656 VM_loadfromdata, // #529
3657 VM_loadfromfile, // #530
3658 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3660 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3661 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3667 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3668 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3669 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3732 VM_callfunction, // #605
3733 VM_writetofile, // #606
3734 VM_isfunction, // #607
3740 VM_parseentitydata, // #613
3751 VM_SV_getextresponse, // #624 string getextresponse(void)
3754 VM_sprintf, // #627 string sprintf(string format, ...)
3755 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3756 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3760 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3762 void VM_SV_Cmd_Init(void)
3767 void VM_SV_Cmd_Reset(void)
3769 World_End(&sv.world);
3770 if(PRVM_serverfunction(SV_Shutdown))
3772 func_t s = PRVM_serverfunction(SV_Shutdown);
3773 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3774 PRVM_ExecuteProgram(s,"SV_Shutdown() required");