6 //============================================================================
11 const char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
24 "DP_CSQC_ENTITYNOCULL "
25 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
26 "DP_CSQC_MULTIFRAME_INTERPOLATION "
27 "DP_CSQC_BOXPARTICLES "
28 "DP_CSQC_SPAWNPARTICLE "
29 "DP_CSQC_QUERYRENDERENTITY "
30 "DP_CSQC_ROTATEMOVES "
43 "DP_EF_RESTARTANIM_BIT "
48 "DP_ENT_CUSTOMCOLORMAP "
49 "DP_ENT_EXTERIORMODELTOCLIENT "
52 "DP_ENT_LOWPRECISION "
54 "DP_ENT_TRAILEFFECTNUM "
57 "DP_GFX_EXTERNALTEXTURES "
58 "DP_GFX_EXTERNALTEXTURES_PERMAP "
60 "DP_GFX_MODEL_INTERPOLATION "
61 "DP_GFX_QUAKE3MODELTAGS "
65 "DP_GFX_FONTS_FREETYPE "
67 "DP_FONT_VARIABLEWIDTH "
69 "DP_HALFLIFE_MAP_CVAR "
72 "DP_LIGHTSTYLE_STATICVALUE "
76 "DP_MOVETYPEBOUNCEMISSILE "
77 "DP_MOVETYPEFLYWORLDONLY "
80 "DP_QC_ASINACOSATANATAN2TAN "
86 "DP_QC_CVAR_DEFSTRING "
87 "DP_QC_CVAR_DESCRIPTION "
94 "DP_QC_EXTRESPONSEPACKET "
96 "DP_QC_FINDCHAINFLAGS "
97 "DP_QC_FINDCHAINFLOAT "
98 "DP_QC_FINDCHAIN_TOFIELD "
104 "DP_QC_GETSURFACETRIANGLE "
105 "DP_QC_GETSURFACEPOINTATTRIBUTE "
107 "DP_QC_GETTAGINFO_BONEPROPERTIES "
109 "DP_QC_GETTIME_CDTRACK "
112 "DP_QC_MULTIPLETEMPSTRINGS "
113 "DP_QC_NUM_FOR_EDICT "
115 "DP_QC_SINCOSSQRTPOW "
118 "DP_QC_STRINGBUFFERS "
119 "DP_QC_STRINGBUFFERS_CVARLIST "
120 "DP_QC_STRINGCOLORFUNCTIONS "
121 "DP_QC_STRING_CASE_FUNCTIONS "
123 "DP_QC_TOKENIZEBYSEPARATOR "
124 "DP_QC_TOKENIZE_CONSOLE "
127 "DP_QC_TRACE_MOVETYPE_HITMODEL "
128 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
129 "DP_QC_UNLIMITEDTEMPSTRINGS "
133 "DP_QC_VECTOANGLES_WITH_ROLL "
134 "DP_QC_VECTORVECTORS "
141 "DP_SKELETONOBJECTS "
142 "DP_SND_DIRECTIONLESSATTNNONE "
144 "DP_SND_SOUND7_WIP1 "
148 "DP_SND_GETSOUNDTIME "
150 "DP_VIDEO_SUBTITLES "
154 "DP_SV_BOUNCEFACTOR "
155 "DP_SV_CLIENTCAMERA "
156 "DP_SV_CLIENTCOLORS "
159 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
160 "DP_SV_DISCARDABLEDEMO "
161 "DP_SV_DRAWONLYTOCLIENT "
164 "DP_SV_ENTITYCONTENTSTRANSITION "
165 "DP_SV_MODELFLAGS_AS_EFFECTS "
166 "DP_SV_MOVETYPESTEP_LANDEVENT "
168 "DP_SV_NODRAWTOCLIENT "
169 "DP_SV_ONENTITYNOSPAWNFUNCTION "
170 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
172 "DP_SV_PING_PACKETLOSS "
173 "DP_SV_PLAYERPHYSICS "
175 "DP_SV_POINTPARTICLES "
177 "DP_SV_PRECACHEANYTIME "
181 "DP_SV_ROTATINGBMODEL "
185 "DP_SV_SPAWNFUNC_PREFIX "
186 "DP_SV_WRITEPICTURE "
187 "DP_SV_WRITEUNTERMINATEDSTRING "
191 "DP_TE_EXPLOSIONRGB "
193 "DP_TE_PARTICLECUBE "
194 "DP_TE_PARTICLERAIN "
195 "DP_TE_PARTICLESNOW "
197 "DP_TE_QUADEFFECTS1 "
200 "DP_TE_STANDARDEFFECTBUILTINS "
201 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
205 "FTE_CSQC_SKELETONOBJECTS "
208 "KRIMZON_SV_PARSECLIENTCOMMAND "
211 "NEXUIZ_PLAYERMODEL "
213 "PRYDON_CLIENTCURSOR "
214 "TENEBRAE_GFX_DLIGHTS "
217 //"EXT_CSQC " // not ready yet
224 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.
226 setorigin (entity, origin)
229 static void VM_SV_setorigin (void)
234 VM_SAFEPARMCOUNT(2, VM_setorigin);
236 e = PRVM_G_EDICT(OFS_PARM0);
237 if (e == prog->edicts)
239 VM_Warning("setorigin: can not modify world entity\n");
242 if (e->priv.server->free)
244 VM_Warning("setorigin: can not modify free entity\n");
247 org = PRVM_G_VECTOR(OFS_PARM1);
248 VectorCopy (org, PRVM_serveredictvector(e, origin));
252 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
253 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
257 for (i=0 ; i<3 ; i++)
259 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
261 // set derived values
262 VectorCopy (min, PRVM_serveredictvector(e, mins));
263 VectorCopy (max, PRVM_serveredictvector(e, maxs));
264 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
273 the size box is rotated by the current angle
274 LordHavoc: no it isn't...
276 setsize (entity, minvector, maxvector)
279 static void VM_SV_setsize (void)
284 VM_SAFEPARMCOUNT(3, VM_setsize);
286 e = PRVM_G_EDICT(OFS_PARM0);
287 if (e == prog->edicts)
289 VM_Warning("setsize: can not modify world entity\n");
292 if (e->priv.server->free)
294 VM_Warning("setsize: can not modify free entity\n");
297 min = PRVM_G_VECTOR(OFS_PARM1);
298 max = PRVM_G_VECTOR(OFS_PARM2);
299 SetMinMaxSize (e, min, max, false);
307 setmodel(entity, model)
310 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
311 static void VM_SV_setmodel (void)
317 VM_SAFEPARMCOUNT(2, VM_setmodel);
319 e = PRVM_G_EDICT(OFS_PARM0);
320 if (e == prog->edicts)
322 VM_Warning("setmodel: can not modify world entity\n");
325 if (e->priv.server->free)
327 VM_Warning("setmodel: can not modify free entity\n");
330 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
331 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
332 PRVM_serveredictfloat(e, modelindex) = i;
334 mod = SV_GetModelByIndex(i);
338 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
339 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
341 SetMinMaxSize (e, quakemins, quakemaxs, true);
344 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
351 single print to a specific client
353 sprint(clientent, value)
356 static void VM_SV_sprint (void)
360 char string[VM_STRINGTEMP_LENGTH];
362 VM_VarString(1, string, sizeof(string));
364 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
366 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
367 // LordHavoc: div0 requested that sprintto world operate like print
374 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
376 VM_Warning("tried to centerprint to a non-client\n");
380 client = svs.clients + entnum-1;
381 if (!client->netconnection)
384 MSG_WriteChar(&client->netconnection->message,svc_print);
385 MSG_WriteString(&client->netconnection->message, string);
393 single print to a specific client
395 centerprint(clientent, value)
398 static void VM_SV_centerprint (void)
402 char string[VM_STRINGTEMP_LENGTH];
404 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
406 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
408 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
410 VM_Warning("tried to centerprint to a non-client\n");
414 client = svs.clients + entnum-1;
415 if (!client->netconnection)
418 VM_VarString(1, string, sizeof(string));
419 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
420 MSG_WriteString(&client->netconnection->message, string);
427 particle(origin, color, count)
430 static void VM_SV_particle (void)
436 VM_SAFEPARMCOUNT(4, VM_SV_particle);
438 org = PRVM_G_VECTOR(OFS_PARM0);
439 dir = PRVM_G_VECTOR(OFS_PARM1);
440 color = PRVM_G_FLOAT(OFS_PARM2);
441 count = PRVM_G_FLOAT(OFS_PARM3);
442 SV_StartParticle (org, dir, (int)color, (int)count);
452 static void VM_SV_ambientsound (void)
456 float vol, attenuation;
459 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
461 pos = PRVM_G_VECTOR (OFS_PARM0);
462 samp = PRVM_G_STRING(OFS_PARM1);
463 vol = PRVM_G_FLOAT(OFS_PARM2);
464 attenuation = PRVM_G_FLOAT(OFS_PARM3);
466 // check to see if samp was properly precached
467 soundnum = SV_SoundIndex(samp, 1);
475 // add an svc_spawnambient command to the level signon packet
478 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
480 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
482 MSG_WriteVector(&sv.signon, pos, sv.protocol);
484 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
485 MSG_WriteShort (&sv.signon, soundnum);
487 MSG_WriteByte (&sv.signon, soundnum);
489 MSG_WriteByte (&sv.signon, (int)(vol*255));
490 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
498 Each entity can have eight independant sound sources, like voice,
501 Channel 0 is an auto-allocate channel, the others override anything
502 already running on that entity/channel pair.
504 An attenuation of 0 will play full volume everywhere in the level.
505 Larger attenuations will drop off.
509 static void VM_SV_sound (void)
513 prvm_edict_t *entity;
519 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
521 entity = PRVM_G_EDICT(OFS_PARM0);
522 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
523 sample = PRVM_G_STRING(OFS_PARM2);
524 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
527 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
531 attenuation = PRVM_G_FLOAT(OFS_PARM4);
535 pitchchange = PRVM_G_FLOAT(OFS_PARM5);
540 if(channel >= 8 && channel <= 15) // weird QW feature
542 flags |= CHANFLAG_RELIABLE;
547 flags = PRVM_G_FLOAT(OFS_PARM6);
549 if (volume < 0 || volume > 255)
551 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
555 if (attenuation < 0 || attenuation > 4)
557 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
561 channel = CHAN_USER2ENGINE(channel);
563 if (!IS_CHAN(channel))
565 VM_Warning("SV_StartSound: channel must be in range 0-127\n");
569 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE);
576 Follows the same logic as VM_SV_sound, except instead of
577 an entity, an origin for the sound is provided, and channel
578 is omitted (since no entity is being tracked).
582 static void VM_SV_pointsound(void)
589 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
591 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
592 sample = PRVM_G_STRING(OFS_PARM1);
593 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
594 attenuation = PRVM_G_FLOAT(OFS_PARM3);
596 if (volume < 0 || volume > 255)
598 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
602 if (attenuation < 0 || attenuation > 4)
604 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
608 SV_StartPointSound (org, sample, volume, attenuation);
615 Used for use tracing and shot targeting
616 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
617 if the tryents flag is set.
619 traceline (vector1, vector2, movetype, ignore)
622 static void VM_SV_traceline (void)
629 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
631 prog->xfunction->builtinsprofile += 30;
633 v1 = PRVM_G_VECTOR(OFS_PARM0);
634 v2 = PRVM_G_VECTOR(OFS_PARM1);
635 move = (int)PRVM_G_FLOAT(OFS_PARM2);
636 ent = PRVM_G_EDICT(OFS_PARM3);
638 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]))
639 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));
641 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
643 VM_SetTraceGlobals(&trace);
651 Used for use tracing and shot targeting
652 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
653 if the tryents flag is set.
655 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
658 // LordHavoc: added this for my own use, VERY useful, similar to traceline
659 static void VM_SV_tracebox (void)
661 float *v1, *v2, *m1, *m2;
666 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
668 prog->xfunction->builtinsprofile += 30;
670 v1 = PRVM_G_VECTOR(OFS_PARM0);
671 m1 = PRVM_G_VECTOR(OFS_PARM1);
672 m2 = PRVM_G_VECTOR(OFS_PARM2);
673 v2 = PRVM_G_VECTOR(OFS_PARM3);
674 move = (int)PRVM_G_FLOAT(OFS_PARM4);
675 ent = PRVM_G_EDICT(OFS_PARM5);
677 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]))
678 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));
680 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
682 VM_SetTraceGlobals(&trace);
685 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
690 vec3_t original_origin;
691 vec3_t original_velocity;
692 vec3_t original_angles;
693 vec3_t original_avelocity;
696 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
697 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
698 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
699 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
701 gravity = PRVM_serveredictfloat(tossent, gravity);
704 gravity *= sv_gravity.value * 0.025;
706 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
708 SV_CheckVelocity (tossent);
709 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
710 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
711 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
712 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
713 trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
714 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
715 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
717 if (trace.fraction < 1)
721 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
722 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
723 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
724 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
729 static void VM_SV_tracetoss (void)
733 prvm_edict_t *ignore;
735 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
737 prog->xfunction->builtinsprofile += 600;
739 ent = PRVM_G_EDICT(OFS_PARM0);
740 if (ent == prog->edicts)
742 VM_Warning("tracetoss: can not use world entity\n");
745 ignore = PRVM_G_EDICT(OFS_PARM1);
747 trace = SV_Trace_Toss (ent, ignore);
749 VM_SetTraceGlobals(&trace);
752 //============================================================================
754 static int checkpvsbytes;
755 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
757 static int VM_SV_newcheckclient (int check)
763 // cycle to the next one
765 check = bound(1, check, svs.maxclients);
766 if (check == svs.maxclients)
774 prog->xfunction->builtinsprofile++;
776 if (i == svs.maxclients+1)
778 // look up the client's edict
779 ent = PRVM_EDICT_NUM(i);
780 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
781 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
783 // found a valid client (possibly the same one again)
787 // get the PVS for the entity
788 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
790 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
791 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
800 Returns a client (or object that has a client enemy) that would be a
803 If there is more than one valid option, they are cycled each frame
805 If (self.origin + self.viewofs) is not in the PVS of the current target,
806 it is not returned at all.
811 int c_invis, c_notvis;
812 static void VM_SV_checkclient (void)
814 prvm_edict_t *ent, *self;
817 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
819 // find a new check if on a new frame
820 if (sv.time - sv.lastchecktime >= 0.1)
822 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
823 sv.lastchecktime = sv.time;
826 // return check if it might be visible
827 ent = PRVM_EDICT_NUM(sv.lastcheck);
828 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
830 VM_RETURN_EDICT(prog->edicts);
834 // if current entity can't possibly see the check entity, return 0
835 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
836 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
837 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
840 VM_RETURN_EDICT(prog->edicts);
844 // might be able to see it
846 VM_RETURN_EDICT(ent);
849 //============================================================================
855 Checks if an entity is in a point's PVS.
856 Should be fast but can be inexact.
858 float checkpvs(vector viewpos, entity viewee) = #240;
861 static void VM_SV_checkpvs (void)
864 prvm_edict_t *viewee;
869 unsigned char fatpvs[MAX_MAP_LEAFS/8];
872 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
873 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
874 viewee = PRVM_G_EDICT(OFS_PARM1);
876 if(viewee->priv.server->free)
878 VM_Warning("checkpvs: can not check free entity\n");
879 PRVM_G_FLOAT(OFS_RETURN) = 4;
884 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
886 // no PVS support on this worldmodel... darn
887 PRVM_G_FLOAT(OFS_RETURN) = 3;
890 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
893 // viewpos isn't in any PVS... darn
894 PRVM_G_FLOAT(OFS_RETURN) = 2;
897 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
899 // using fat PVS like FTEQW does (slow)
900 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
902 // no PVS support on this worldmodel... darn
903 PRVM_G_FLOAT(OFS_RETURN) = 3;
906 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
909 // viewpos isn't in any PVS... darn
910 PRVM_G_FLOAT(OFS_RETURN) = 2;
913 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
922 Sends text over to the client's execution buffer
924 stuffcmd (clientent, value, ...)
927 static void VM_SV_stuffcmd (void)
931 char string[VM_STRINGTEMP_LENGTH];
933 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
935 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
936 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
938 VM_Warning("Can't stuffcmd to a non-client\n");
942 VM_VarString(1, string, sizeof(string));
945 host_client = svs.clients + entnum-1;
946 Host_ClientCommands ("%s", string);
954 Returns a chain of entities that have origins within a spherical area
956 findradius (origin, radius)
959 static void VM_SV_findradius (void)
961 prvm_edict_t *ent, *chain;
962 vec_t radius, radius2;
963 vec3_t org, eorg, mins, maxs;
966 static prvm_edict_t *touchedicts[MAX_EDICTS];
969 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
972 chainfield = PRVM_G_INT(OFS_PARM2);
974 chainfield = prog->fieldoffsets.chain;
976 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
978 chain = (prvm_edict_t *)prog->edicts;
980 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
981 radius = PRVM_G_FLOAT(OFS_PARM1);
982 radius2 = radius * radius;
984 mins[0] = org[0] - (radius + 1);
985 mins[1] = org[1] - (radius + 1);
986 mins[2] = org[2] - (radius + 1);
987 maxs[0] = org[0] + (radius + 1);
988 maxs[1] = org[1] + (radius + 1);
989 maxs[2] = org[2] + (radius + 1);
990 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
991 if (numtouchedicts > MAX_EDICTS)
993 // this never happens
994 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
995 numtouchedicts = MAX_EDICTS;
997 for (i = 0;i < numtouchedicts;i++)
999 ent = touchedicts[i];
1000 prog->xfunction->builtinsprofile++;
1001 // Quake did not return non-solid entities but darkplaces does
1002 // (note: this is the reason you can't blow up fallen zombies)
1003 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1005 // LordHavoc: compare against bounding box rather than center so it
1006 // doesn't miss large objects, and use DotProduct instead of Length
1007 // for a major speedup
1008 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1009 if (sv_gameplayfix_findradiusdistancetobox.integer)
1011 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1012 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1013 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1016 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1017 if (DotProduct(eorg, eorg) < radius2)
1019 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1024 VM_RETURN_EDICT(chain);
1027 static void VM_SV_precache_sound (void)
1029 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1030 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1033 static void VM_SV_precache_model (void)
1035 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1036 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1037 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1044 float(float yaw, float dist[, settrace]) walkmove
1047 static void VM_SV_walkmove (void)
1056 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1058 // assume failure if it returns early
1059 PRVM_G_FLOAT(OFS_RETURN) = 0;
1061 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1062 if (ent == prog->edicts)
1064 VM_Warning("walkmove: can not modify world entity\n");
1067 if (ent->priv.server->free)
1069 VM_Warning("walkmove: can not modify free entity\n");
1072 yaw = PRVM_G_FLOAT(OFS_PARM0);
1073 dist = PRVM_G_FLOAT(OFS_PARM1);
1074 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1076 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1079 yaw = yaw*M_PI*2 / 360;
1081 move[0] = cos(yaw)*dist;
1082 move[1] = sin(yaw)*dist;
1085 // save program state, because SV_movestep may call other progs
1086 oldf = prog->xfunction;
1087 oldself = PRVM_serverglobaledict(self);
1089 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1092 // restore program state
1093 prog->xfunction = oldf;
1094 PRVM_serverglobaledict(self) = oldself;
1104 static void VM_SV_droptofloor (void)
1110 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1112 // assume failure if it returns early
1113 PRVM_G_FLOAT(OFS_RETURN) = 0;
1115 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1116 if (ent == prog->edicts)
1118 VM_Warning("droptofloor: can not modify world entity\n");
1121 if (ent->priv.server->free)
1123 VM_Warning("droptofloor: can not modify free entity\n");
1127 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1130 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1131 SV_UnstickEntity(ent);
1133 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1134 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1137 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]);
1138 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1139 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1140 VectorSubtract(trace.endpos, offset, trace.endpos);
1141 if (trace.startsolid)
1143 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]);
1144 SV_UnstickEntity(ent);
1146 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1147 PRVM_serveredictedict(ent, groundentity) = 0;
1148 PRVM_G_FLOAT(OFS_RETURN) = 1;
1150 else if (trace.fraction < 1)
1152 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]);
1153 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1154 SV_UnstickEntity(ent);
1156 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1157 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1158 PRVM_G_FLOAT(OFS_RETURN) = 1;
1159 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1160 ent->priv.server->suspendedinairflag = true;
1165 if (trace.fraction != 1)
1167 if (trace.fraction < 1)
1168 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1170 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1171 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1172 PRVM_G_FLOAT(OFS_RETURN) = 1;
1173 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1174 ent->priv.server->suspendedinairflag = true;
1183 void(float style, string value) lightstyle
1186 static void VM_SV_lightstyle (void)
1193 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1195 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1196 val = PRVM_G_STRING(OFS_PARM1);
1198 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1199 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1202 // change the string in sv
1203 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1205 // send message to all clients on this server
1206 if (sv.state != ss_active)
1209 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1211 if (client->active && client->netconnection)
1213 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1214 MSG_WriteChar (&client->netconnection->message,style);
1215 MSG_WriteString (&client->netconnection->message, val);
1225 static void VM_SV_checkbottom (void)
1227 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1228 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1236 static void VM_SV_pointcontents (void)
1238 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1239 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1246 Pick a vector for the player to shoot along
1247 vector aim(entity, missilespeed)
1250 static void VM_SV_aim (void)
1252 prvm_edict_t *ent, *check, *bestent;
1253 vec3_t start, dir, end, bestdir;
1256 float dist, bestdist;
1259 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1261 // assume failure if it returns early
1262 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1263 // if sv_aim is so high it can't possibly accept anything, skip out early
1264 if (sv_aim.value >= 1)
1267 ent = PRVM_G_EDICT(OFS_PARM0);
1268 if (ent == prog->edicts)
1270 VM_Warning("aim: can not use world entity\n");
1273 if (ent->priv.server->free)
1275 VM_Warning("aim: can not use free entity\n");
1278 //speed = PRVM_G_FLOAT(OFS_PARM1);
1280 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1283 // try sending a trace straight
1284 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1285 VectorMA (start, 2048, dir, end);
1286 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1287 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1288 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1290 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1295 // try all possible entities
1296 VectorCopy (dir, bestdir);
1297 bestdist = sv_aim.value;
1300 check = PRVM_NEXT_EDICT(prog->edicts);
1301 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1303 prog->xfunction->builtinsprofile++;
1304 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1308 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1309 continue; // don't aim at teammate
1310 for (j=0 ; j<3 ; j++)
1311 end[j] = PRVM_serveredictvector(check, origin)[j]
1312 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1313 VectorSubtract (end, start, dir);
1314 VectorNormalize (dir);
1315 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1316 if (dist < bestdist)
1317 continue; // to far to turn
1318 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1319 if (tr.ent == check)
1320 { // can shoot at this one
1328 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1329 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1330 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1332 VectorNormalize (end);
1333 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1337 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1342 ===============================================================================
1346 ===============================================================================
1349 #define MSG_BROADCAST 0 // unreliable to all
1350 #define MSG_ONE 1 // reliable to one (msg_entity)
1351 #define MSG_ALL 2 // reliable to all
1352 #define MSG_INIT 3 // write to the init string
1353 #define MSG_ENTITY 5
1355 sizebuf_t *WriteDest (void)
1361 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1365 return &sv.datagram;
1368 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1369 entnum = PRVM_NUM_FOR_EDICT(ent);
1370 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1372 VM_Warning ("WriteDest: tried to write to non-client\n");
1373 return &sv.reliable_datagram;
1376 return &svs.clients[entnum-1].netconnection->message;
1379 VM_Warning ("WriteDest: bad destination\n");
1381 return &sv.reliable_datagram;
1387 return sv.writeentitiestoclient_msg;
1393 static void VM_SV_WriteByte (void)
1395 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1396 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1399 static void VM_SV_WriteChar (void)
1401 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1402 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1405 static void VM_SV_WriteShort (void)
1407 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1408 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1411 static void VM_SV_WriteLong (void)
1413 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1414 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1417 static void VM_SV_WriteAngle (void)
1419 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1420 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1423 static void VM_SV_WriteCoord (void)
1425 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1426 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1429 static void VM_SV_WriteString (void)
1431 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1432 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1435 static void VM_SV_WriteUnterminatedString (void)
1437 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1438 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1442 static void VM_SV_WriteEntity (void)
1444 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1445 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1448 // writes a picture as at most size bytes of data
1450 // IMGNAME \0 SIZE(short) IMGDATA
1451 // if failed to read/compress:
1453 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1454 static void VM_SV_WritePicture (void)
1456 const char *imgname;
1460 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1462 imgname = PRVM_G_STRING(OFS_PARM1);
1463 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1467 MSG_WriteString(WriteDest(), imgname);
1468 if(Image_Compress(imgname, size, &buf, &size))
1471 MSG_WriteShort(WriteDest(), size);
1472 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1477 MSG_WriteShort(WriteDest(), 0);
1481 //////////////////////////////////////////////////////////
1483 static void VM_SV_makestatic (void)
1488 // allow 0 parameters due to an id1 qc bug in which this function is used
1489 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1490 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1492 if (prog->argc >= 1)
1493 ent = PRVM_G_EDICT(OFS_PARM0);
1495 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1496 if (ent == prog->edicts)
1498 VM_Warning("makestatic: can not modify world entity\n");
1501 if (ent->priv.server->free)
1503 VM_Warning("makestatic: can not modify free entity\n");
1508 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1513 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1514 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1515 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1517 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1519 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1520 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1521 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1525 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1526 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1527 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1530 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1531 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1532 for (i=0 ; i<3 ; i++)
1534 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1535 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1538 // throw the entity away now
1542 //=============================================================================
1549 static void VM_SV_setspawnparms (void)
1555 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1557 ent = PRVM_G_EDICT(OFS_PARM0);
1558 i = PRVM_NUM_FOR_EDICT(ent);
1559 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1561 Con_Print("tried to setspawnparms on a non-client\n");
1565 // copy spawn parms out of the client_t
1566 client = svs.clients + i-1;
1567 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1568 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1575 Returns a color vector indicating the lighting at the requested point.
1577 (Internal Operation note: actually measures the light beneath the point, just like
1578 the model lighting on the client)
1583 static void VM_SV_getlight (void)
1585 vec3_t ambientcolor, diffusecolor, diffusenormal;
1587 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1588 p = PRVM_G_VECTOR(OFS_PARM0);
1589 VectorClear(ambientcolor);
1590 VectorClear(diffusecolor);
1591 VectorClear(diffusenormal);
1592 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1593 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1594 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1599 unsigned char type; // 1/2/8 or other value if isn't used
1603 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1604 static int vm_customstats_last;
1606 void VM_CustomStats_Clear (void)
1610 Z_Free(vm_customstats);
1611 vm_customstats = NULL;
1612 vm_customstats_last = -1;
1616 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1624 for(i=0; i<vm_customstats_last+1 ;i++)
1626 if(!vm_customstats[i].type)
1628 switch(vm_customstats[i].type)
1630 //string as 16 bytes
1633 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1634 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1635 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1636 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1637 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1639 //float field sent as-is
1641 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1643 //integer value of float field
1645 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1653 // void(float index, float type, .void field) SV_AddStat = #232;
1654 // Set up an auto-sent player stat.
1655 // Client's get thier own fields sent to them. Index may not be less than 32.
1656 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1657 // 1: string (4 stats carrying a total of 16 charactures)
1658 // 2: float (one stat, float converted to an integer for transportation)
1659 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1660 static void VM_SV_AddStat (void)
1665 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1669 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1672 VM_Warning("PF_SV_AddStat: not enough memory\n");
1676 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1677 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1678 off = PRVM_G_INT (OFS_PARM2);
1683 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1686 if(i >= (MAX_CL_STATS-32))
1688 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1691 if(i > (MAX_CL_STATS-32-4) && type == 1)
1693 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1696 vm_customstats[i].type = type;
1697 vm_customstats[i].fieldoffset = off;
1698 if(vm_customstats_last < i)
1699 vm_customstats_last = i;
1706 copies data from one entity to another
1708 copyentity(src, dst)
1711 static void VM_SV_copyentity (void)
1713 prvm_edict_t *in, *out;
1714 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1715 in = PRVM_G_EDICT(OFS_PARM0);
1716 if (in == prog->edicts)
1718 VM_Warning("copyentity: can not read world entity\n");
1721 if (in->priv.server->free)
1723 VM_Warning("copyentity: can not read free entity\n");
1726 out = PRVM_G_EDICT(OFS_PARM1);
1727 if (out == prog->edicts)
1729 VM_Warning("copyentity: can not modify world entity\n");
1732 if (out->priv.server->free)
1734 VM_Warning("copyentity: can not modify free entity\n");
1737 memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
1746 sets the color of a client and broadcasts the update to all connected clients
1748 setcolor(clientent, value)
1751 static void VM_SV_setcolor (void)
1756 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1757 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1758 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1760 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1762 Con_Print("tried to setcolor a non-client\n");
1766 client = svs.clients + entnum-1;
1769 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1770 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1773 if (client->old_colors != client->colors)
1775 client->old_colors = client->colors;
1776 // send notification to all clients
1777 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1778 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1779 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1787 effect(origin, modelname, startframe, framecount, framerate)
1790 static void VM_SV_effect (void)
1794 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1795 s = PRVM_G_STRING(OFS_PARM1);
1798 VM_Warning("effect: no model specified\n");
1802 i = SV_ModelIndex(s, 1);
1805 VM_Warning("effect: model not precached\n");
1809 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1811 VM_Warning("effect: framecount < 1\n");
1815 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1817 VM_Warning("effect: framerate < 1\n");
1821 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));
1824 static void VM_SV_te_blood (void)
1826 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1827 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1829 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1830 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1832 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1833 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1834 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1836 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1837 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1838 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1840 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1841 SV_FlushBroadcastMessages();
1844 static void VM_SV_te_bloodshower (void)
1846 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1847 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1849 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1850 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1852 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1853 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1854 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1856 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1857 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1858 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1860 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1862 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1863 SV_FlushBroadcastMessages();
1866 static void VM_SV_te_explosionrgb (void)
1868 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1869 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1870 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1873 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1874 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1876 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1877 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1878 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1879 SV_FlushBroadcastMessages();
1882 static void VM_SV_te_particlecube (void)
1884 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1885 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1887 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1888 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1890 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1891 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1892 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1894 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1895 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1896 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1900 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1902 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1904 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1905 // gravity true/false
1906 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1909 SV_FlushBroadcastMessages();
1912 static void VM_SV_te_particlerain (void)
1914 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1915 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1917 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1918 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1920 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1921 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1922 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1924 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1925 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1926 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1932 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1934 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1935 SV_FlushBroadcastMessages();
1938 static void VM_SV_te_particlesnow (void)
1940 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1941 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1943 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1944 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1948 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1950 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1952 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1954 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1955 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1958 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1960 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1961 SV_FlushBroadcastMessages();
1964 static void VM_SV_te_spark (void)
1966 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1967 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1969 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1970 MSG_WriteByte(&sv.datagram, TE_SPARK);
1972 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1973 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1974 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1976 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1977 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1978 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1980 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1981 SV_FlushBroadcastMessages();
1984 static void VM_SV_te_gunshotquad (void)
1986 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1987 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1988 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
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_spikequad (void)
1998 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1999 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2000 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
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_superspikequad (void)
2010 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2011 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2012 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
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_explosionquad (void)
2022 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2023 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2024 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2026 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2028 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2029 SV_FlushBroadcastMessages();
2032 static void VM_SV_te_smallflash (void)
2034 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2035 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2036 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2038 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2039 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2040 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2041 SV_FlushBroadcastMessages();
2044 static void VM_SV_te_customflash (void)
2046 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2047 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2049 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2050 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2052 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2054 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2056 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2058 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2060 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2061 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2062 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2063 SV_FlushBroadcastMessages();
2066 static void VM_SV_te_gunshot (void)
2068 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2069 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2070 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
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_spike (void)
2080 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2081 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2082 MSG_WriteByte(&sv.datagram, TE_SPIKE);
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_superspike (void)
2092 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2093 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2094 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
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_explosion (void)
2104 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2105 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2106 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
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_tarexplosion (void)
2116 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2117 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2118 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
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_wizspike (void)
2128 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2129 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2130 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
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_knightspike (void)
2140 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2141 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2142 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
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_lavasplash (void)
2152 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2153 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2154 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
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);
2159 SV_FlushBroadcastMessages();
2162 static void VM_SV_te_teleport (void)
2164 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2165 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2166 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2168 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2169 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2170 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2171 SV_FlushBroadcastMessages();
2174 static void VM_SV_te_explosion2 (void)
2176 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2177 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2178 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2180 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2181 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2182 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2184 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2185 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2186 SV_FlushBroadcastMessages();
2189 static void VM_SV_te_lightning1 (void)
2191 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2192 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2193 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2195 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2197 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2198 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2199 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2201 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2202 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2203 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2204 SV_FlushBroadcastMessages();
2207 static void VM_SV_te_lightning2 (void)
2209 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2210 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2211 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2213 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2215 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2216 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2217 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2219 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2220 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2221 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2222 SV_FlushBroadcastMessages();
2225 static void VM_SV_te_lightning3 (void)
2227 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2228 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2229 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2231 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2234 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2235 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2237 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2238 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2239 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2240 SV_FlushBroadcastMessages();
2243 static void VM_SV_te_beam (void)
2245 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2246 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2247 MSG_WriteByte(&sv.datagram, TE_BEAM);
2249 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2251 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2252 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2253 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2255 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2256 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2257 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2258 SV_FlushBroadcastMessages();
2261 static void VM_SV_te_plasmaburn (void)
2263 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2264 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2265 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2266 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2267 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2268 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2269 SV_FlushBroadcastMessages();
2272 static void VM_SV_te_flamejet (void)
2274 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2275 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2276 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2278 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2279 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2280 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2282 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2283 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2284 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2286 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2287 SV_FlushBroadcastMessages();
2290 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2291 //this function originally written by KrimZon, made shorter by LordHavoc
2292 static void VM_SV_clientcommand (void)
2294 client_t *temp_client;
2296 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2298 //find client for this entity
2299 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2300 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2302 Con_Print("PF_clientcommand: entity is not a client\n");
2306 temp_client = host_client;
2307 host_client = svs.clients + i;
2308 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2309 host_client = temp_client;
2312 //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)
2313 static void VM_SV_setattachment (void)
2315 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2316 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2317 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2320 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2322 if (e == prog->edicts)
2324 VM_Warning("setattachment: can not modify world entity\n");
2327 if (e->priv.server->free)
2329 VM_Warning("setattachment: can not modify free entity\n");
2333 if (tagentity == NULL)
2334 tagentity = prog->edicts;
2338 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2340 model = SV_GetModelFromEdict(tagentity);
2343 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2345 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);
2348 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));
2351 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2352 PRVM_serveredictfloat(e, tag_index) = tagindex;
2355 /////////////////////////////////////////
2356 // DP_MD3_TAGINFO extension coded by VorteX
2358 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2362 i = (int)PRVM_serveredictfloat(e, modelindex);
2363 if (i < 1 || i >= MAX_MODELS)
2366 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2369 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2376 Matrix4x4_CreateIdentity(tag_localmatrix);
2378 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2380 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2391 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2394 float pitchsign = 1;
2396 scale = PRVM_serveredictfloat(ent, scale);
2401 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);
2404 pitchsign = SV_GetPitchSign(ent);
2405 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);
2409 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2412 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2414 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2415 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2416 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2417 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2419 *out = identitymatrix;
2423 // Warnings/errors code:
2424 // 0 - normal (everything all-right)
2427 // 3 - null or non-precached model
2428 // 4 - no tags with requested index
2429 // 5 - runaway loop at attachment chain
2430 extern cvar_t cl_bob;
2431 extern cvar_t cl_bobcycle;
2432 extern cvar_t cl_bobup;
2433 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2436 int modelindex, attachloop;
2437 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2440 *out = identitymatrix; // warnings and errors return identical matrix
2442 if (ent == prog->edicts)
2444 if (ent->priv.server->free)
2447 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2448 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2451 model = SV_GetModelByIndex(modelindex);
2453 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2454 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2455 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2457 tagmatrix = identitymatrix;
2458 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2462 if (attachloop >= 256) // prevent runaway looping
2464 // apply transformation by child's tagindex on parent entity and then
2465 // by parent entity itself
2466 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2467 if (ret && attachloop == 0)
2469 SV_GetEntityMatrix(ent, &entitymatrix, false);
2470 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2471 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2472 // next iteration we process the parent entity
2473 if (PRVM_serveredictedict(ent, tag_entity))
2475 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2476 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2483 // RENDER_VIEWMODEL magic
2484 if (PRVM_serveredictedict(ent, viewmodelforclient))
2486 Matrix4x4_Copy(&tagmatrix, out);
2487 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2489 SV_GetEntityMatrix(ent, &entitymatrix, true);
2490 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2493 // Cl_bob, ported from rendering code
2494 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2497 // LordHavoc: this code is *weird*, but not replacable (I think it
2498 // should be done in QC on the server, but oh well, quake is quake)
2499 // LordHavoc: figured out bobup: the time at which the sin is at 180
2500 // degrees (which allows lengthening or squishing the peak or valley)
2501 cycle = sv.time/cl_bobcycle.value;
2502 cycle -= (int)cycle;
2503 if (cycle < cl_bobup.value)
2504 cycle = sin(M_PI * cycle / cl_bobup.value);
2506 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2507 // bob is proportional to velocity in the xy plane
2508 // (don't count Z, or jumping messes it up)
2509 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;
2510 bob = bob*0.3 + bob*0.7*cycle;
2511 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2518 //float(entity ent, string tagname) gettagindex;
2520 static void VM_SV_gettagindex (void)
2523 const char *tag_name;
2526 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2528 ent = PRVM_G_EDICT(OFS_PARM0);
2529 tag_name = PRVM_G_STRING(OFS_PARM1);
2531 if (ent == prog->edicts)
2533 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2536 if (ent->priv.server->free)
2538 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2543 if (!SV_GetModelFromEdict(ent))
2544 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2547 tag_index = SV_GetTagIndex(ent, tag_name);
2549 if(developer_extra.integer)
2550 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2552 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2555 //vector(entity ent, float tagindex) gettaginfo;
2556 static void VM_SV_gettaginfo (void)
2560 matrix4x4_t tag_matrix;
2561 matrix4x4_t tag_localmatrix;
2563 const char *tagname;
2565 vec3_t fo, le, up, trans;
2566 const dp_model_t *model;
2568 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2570 e = PRVM_G_EDICT(OFS_PARM0);
2571 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2573 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2574 Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
2575 VectorScale(le, -1, PRVM_serverglobalvector(v_right));
2576 model = SV_GetModelFromEdict(e);
2577 VM_GenerateFrameGroupBlend(e->priv.server->framegroupblend, e);
2578 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
2579 VM_UpdateEdictSkeleton(e, model, e->priv.server->frameblend);
2580 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2581 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2583 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2584 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(tagname) : 0;
2585 VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
2586 VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
2587 VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
2588 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2593 VM_Warning("gettagindex: can't affect world entity\n");
2596 VM_Warning("gettagindex: can't affect free entity\n");
2599 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2602 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2605 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2610 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2611 static void VM_SV_dropclient (void)
2614 client_t *oldhostclient;
2615 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2616 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2617 if (clientnum < 0 || clientnum >= svs.maxclients)
2619 VM_Warning("dropclient: not a client\n");
2622 if (!svs.clients[clientnum].active)
2624 VM_Warning("dropclient: that client slot is not connected\n");
2627 oldhostclient = host_client;
2628 host_client = svs.clients + clientnum;
2629 SV_DropClient(false);
2630 host_client = oldhostclient;
2633 //entity() spawnclient (DP_SV_BOTCLIENT)
2634 static void VM_SV_spawnclient (void)
2638 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2639 prog->xfunction->builtinsprofile += 2;
2641 for (i = 0;i < svs.maxclients;i++)
2643 if (!svs.clients[i].active)
2645 prog->xfunction->builtinsprofile += 100;
2646 SV_ConnectClient (i, NULL);
2647 // this has to be set or else ClientDisconnect won't be called
2648 // we assume the qc will call ClientConnect...
2649 svs.clients[i].clientconnectcalled = true;
2650 ed = PRVM_EDICT_NUM(i + 1);
2654 VM_RETURN_EDICT(ed);
2657 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2658 static void VM_SV_clienttype (void)
2661 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2662 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2663 if (clientnum < 0 || clientnum >= svs.maxclients)
2664 PRVM_G_FLOAT(OFS_RETURN) = 3;
2665 else if (!svs.clients[clientnum].active)
2666 PRVM_G_FLOAT(OFS_RETURN) = 0;
2667 else if (svs.clients[clientnum].netconnection)
2668 PRVM_G_FLOAT(OFS_RETURN) = 1;
2670 PRVM_G_FLOAT(OFS_RETURN) = 2;
2677 string(string key) serverkey
2680 void VM_SV_serverkey(void)
2682 char string[VM_STRINGTEMP_LENGTH];
2683 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2684 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2685 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2688 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2689 static void VM_SV_setmodelindex (void)
2694 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2696 e = PRVM_G_EDICT(OFS_PARM0);
2697 if (e == prog->edicts)
2699 VM_Warning("setmodelindex: can not modify world entity\n");
2702 if (e->priv.server->free)
2704 VM_Warning("setmodelindex: can not modify free entity\n");
2707 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2708 if (i <= 0 || i >= MAX_MODELS)
2710 VM_Warning("setmodelindex: invalid modelindex\n");
2713 if (!sv.model_precache[i][0])
2715 VM_Warning("setmodelindex: model not precached\n");
2719 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
2720 PRVM_serveredictfloat(e, modelindex) = i;
2722 mod = SV_GetModelByIndex(i);
2726 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2727 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2729 SetMinMaxSize (e, quakemins, quakemaxs, true);
2732 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2735 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2736 static void VM_SV_modelnameforindex (void)
2739 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2741 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2743 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2744 if (i <= 0 || i >= MAX_MODELS)
2746 VM_Warning("modelnameforindex: invalid modelindex\n");
2749 if (!sv.model_precache[i][0])
2751 VM_Warning("modelnameforindex: model not precached\n");
2755 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2758 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2759 static void VM_SV_particleeffectnum (void)
2762 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2763 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2766 PRVM_G_FLOAT(OFS_RETURN) = i;
2769 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2770 static void VM_SV_trailparticles (void)
2772 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2774 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2777 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2778 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2779 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2780 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2781 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2782 SV_FlushBroadcastMessages();
2785 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2786 static void VM_SV_pointparticles (void)
2788 int effectnum, count;
2790 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2792 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2795 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2796 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2797 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2798 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2799 if (count == 1 && !VectorLength2(vel))
2802 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2803 MSG_WriteShort(&sv.datagram, effectnum);
2804 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2808 // 1+2+12+12+2=29 bytes
2809 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2810 MSG_WriteShort(&sv.datagram, effectnum);
2811 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2812 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2813 MSG_WriteShort(&sv.datagram, count);
2816 SV_FlushBroadcastMessages();
2819 //PF_setpause, // void(float pause) setpause = #531;
2820 static void VM_SV_setpause(void) {
2822 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2823 if (pauseValue != 0) { //pause the game
2825 sv.pausedstart = Sys_DoubleTime();
2826 } else { //disable pause, in case it was enabled
2827 if (sv.paused != 0) {
2832 // send notification to all clients
2833 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2834 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2837 // #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.
2838 static void VM_SV_skel_create(void)
2840 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2841 dp_model_t *model = SV_GetModelByIndex(modelindex);
2842 skeleton_t *skeleton;
2844 PRVM_G_FLOAT(OFS_RETURN) = 0;
2845 if (!model || !model->num_bones)
2847 for (i = 0;i < MAX_EDICTS;i++)
2848 if (!prog->skeletons[i])
2850 if (i == MAX_EDICTS)
2852 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2853 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2854 skeleton->model = model;
2855 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2856 // initialize to identity matrices
2857 for (i = 0;i < skeleton->model->num_bones;i++)
2858 skeleton->relativetransforms[i] = identitymatrix;
2861 // #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
2862 static void VM_SV_skel_build(void)
2864 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2865 skeleton_t *skeleton;
2866 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2867 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2868 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2869 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2870 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2871 dp_model_t *model = SV_GetModelByIndex(modelindex);
2876 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2877 frameblend_t frameblend[MAX_FRAMEBLENDS];
2878 matrix4x4_t blendedmatrix;
2880 PRVM_G_FLOAT(OFS_RETURN) = 0;
2881 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2883 firstbone = max(0, firstbone);
2884 lastbone = min(lastbone, model->num_bones - 1);
2885 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2886 VM_GenerateFrameGroupBlend(framegroupblend, ed);
2887 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
2888 blendfrac = 1.0f - retainfrac;
2889 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2890 frameblend[numblends].lerp *= blendfrac;
2891 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2893 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2894 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2895 for (blendindex = 0;blendindex < numblends;blendindex++)
2897 Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2898 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2900 skeleton->relativetransforms[bonenum] = blendedmatrix;
2902 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2905 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2906 static void VM_SV_skel_get_numbones(void)
2908 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2909 skeleton_t *skeleton;
2910 PRVM_G_FLOAT(OFS_RETURN) = 0;
2911 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2913 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2916 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2917 static void VM_SV_skel_get_bonename(void)
2919 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2920 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2921 skeleton_t *skeleton;
2922 PRVM_G_INT(OFS_RETURN) = 0;
2923 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2925 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2927 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(skeleton->model->data_bones[bonenum].name);
2930 // #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)
2931 static void VM_SV_skel_get_boneparent(void)
2933 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2934 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2935 skeleton_t *skeleton;
2936 PRVM_G_FLOAT(OFS_RETURN) = 0;
2937 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2939 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2941 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2944 // #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
2945 static void VM_SV_skel_find_bone(void)
2947 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2948 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2949 skeleton_t *skeleton;
2950 PRVM_G_FLOAT(OFS_RETURN) = 0;
2951 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2953 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2956 // #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)
2957 static void VM_SV_skel_get_bonerel(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;
2963 vec3_t forward, left, up, origin;
2964 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2965 VectorClear(PRVM_clientglobalvector(v_forward));
2966 VectorClear(PRVM_clientglobalvector(v_right));
2967 VectorClear(PRVM_clientglobalvector(v_up));
2968 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2970 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2972 matrix = skeleton->relativetransforms[bonenum];
2973 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2974 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2975 VectorNegate(left, PRVM_clientglobalvector(v_right));
2976 VectorCopy(up, PRVM_clientglobalvector(v_up));
2977 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2980 // #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)
2981 static void VM_SV_skel_get_boneabs(void)
2983 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2984 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2985 skeleton_t *skeleton;
2988 vec3_t forward, left, up, origin;
2989 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2990 VectorClear(PRVM_clientglobalvector(v_forward));
2991 VectorClear(PRVM_clientglobalvector(v_right));
2992 VectorClear(PRVM_clientglobalvector(v_up));
2993 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2995 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2997 matrix = skeleton->relativetransforms[bonenum];
2998 // convert to absolute
2999 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3002 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3004 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3005 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3006 VectorNegate(left, PRVM_clientglobalvector(v_right));
3007 VectorCopy(up, PRVM_clientglobalvector(v_up));
3008 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3011 // #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)
3012 static void VM_SV_skel_set_bone(void)
3014 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3015 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3016 vec3_t forward, left, up, origin;
3017 skeleton_t *skeleton;
3019 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3021 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3023 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3024 VectorNegate(PRVM_clientglobalvector(v_right), left);
3025 VectorCopy(PRVM_clientglobalvector(v_up), up);
3026 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3027 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3028 skeleton->relativetransforms[bonenum] = matrix;
3031 // #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)
3032 static void VM_SV_skel_mul_bone(void)
3034 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3035 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3036 vec3_t forward, left, up, origin;
3037 skeleton_t *skeleton;
3040 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3042 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3044 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3045 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3046 VectorNegate(PRVM_clientglobalvector(v_right), left);
3047 VectorCopy(PRVM_clientglobalvector(v_up), up);
3048 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3049 temp = skeleton->relativetransforms[bonenum];
3050 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3053 // #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)
3054 static void VM_SV_skel_mul_bones(void)
3056 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3057 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3058 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3060 vec3_t forward, left, up, origin;
3061 skeleton_t *skeleton;
3064 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3066 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3067 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3068 VectorNegate(PRVM_clientglobalvector(v_right), left);
3069 VectorCopy(PRVM_clientglobalvector(v_up), up);
3070 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3071 firstbone = max(0, firstbone);
3072 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3073 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3075 temp = skeleton->relativetransforms[bonenum];
3076 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3080 // #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
3081 static void VM_SV_skel_copybones(void)
3083 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3084 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3085 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3086 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3088 skeleton_t *skeletondst;
3089 skeleton_t *skeletonsrc;
3090 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3092 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3094 firstbone = max(0, firstbone);
3095 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3096 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3097 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3098 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3101 // #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)
3102 static void VM_SV_skel_delete(void)
3104 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3105 skeleton_t *skeleton;
3106 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3109 prog->skeletons[skeletonindex] = NULL;
3112 // #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
3113 static void VM_SV_frameforname(void)
3115 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3116 dp_model_t *model = SV_GetModelByIndex(modelindex);
3117 const char *name = PRVM_G_STRING(OFS_PARM1);
3119 PRVM_G_FLOAT(OFS_RETURN) = -1;
3120 if (!model || !model->animscenes)
3122 for (i = 0;i < model->numframes;i++)
3124 if (!strcasecmp(model->animscenes[i].name, name))
3126 PRVM_G_FLOAT(OFS_RETURN) = i;
3132 // #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.
3133 static void VM_SV_frameduration(void)
3135 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3136 dp_model_t *model = SV_GetModelByIndex(modelindex);
3137 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3138 PRVM_G_FLOAT(OFS_RETURN) = 0;
3139 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3141 if (model->animscenes[framenum].framerate)
3142 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3146 prvm_builtin_t vm_sv_builtins[] = {
3147 NULL, // #0 NULL function (not callable) (QUAKE)
3148 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3149 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3150 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3151 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3152 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3153 VM_break, // #6 void() break (QUAKE)
3154 VM_random, // #7 float() random (QUAKE)
3155 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3156 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3157 VM_error, // #10 void(string e) error (QUAKE)
3158 VM_objerror, // #11 void(string e) objerror (QUAKE)
3159 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3160 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3161 VM_spawn, // #14 entity() spawn (QUAKE)
3162 VM_remove, // #15 void(entity e) remove (QUAKE)
3163 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3164 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3165 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3166 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3167 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3168 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3169 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3170 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3171 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3172 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3173 VM_ftos, // #26 string(float f) ftos (QUAKE)
3174 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3175 VM_coredump, // #28 void() coredump (QUAKE)
3176 VM_traceon, // #29 void() traceon (QUAKE)
3177 VM_traceoff, // #30 void() traceoff (QUAKE)
3178 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3179 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3180 NULL, // #33 (QUAKE)
3181 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3182 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3183 VM_rint, // #36 float(float v) rint (QUAKE)
3184 VM_floor, // #37 float(float v) floor (QUAKE)
3185 VM_ceil, // #38 float(float v) ceil (QUAKE)
3186 NULL, // #39 (QUAKE)
3187 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3188 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3189 NULL, // #42 (QUAKE)
3190 VM_fabs, // #43 float(float f) fabs (QUAKE)
3191 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3192 VM_cvar, // #45 float(string s) cvar (QUAKE)
3193 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3194 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3195 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3196 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3197 NULL, // #50 (QUAKE)
3198 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3199 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3200 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3201 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3202 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3203 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3204 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3205 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3206 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3207 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3208 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3209 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3210 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3211 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3212 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3213 NULL, // #66 (QUAKE)
3214 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3215 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3216 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3217 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3218 NULL, // #71 (QUAKE)
3219 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3220 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3221 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3222 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3223 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3224 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3225 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3226 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3227 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3228 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3229 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3230 NULL, // #83 (QUAKE)
3231 NULL, // #84 (QUAKE)
3232 NULL, // #85 (QUAKE)
3233 NULL, // #86 (QUAKE)
3234 NULL, // #87 (QUAKE)
3235 NULL, // #88 (QUAKE)
3236 NULL, // #89 (QUAKE)
3237 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3238 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3239 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3240 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3241 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3242 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3243 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3244 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3245 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3246 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3247 // FrikaC and Telejano range #100-#199
3258 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3259 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3260 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3261 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3262 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3263 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3264 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3265 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3266 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3267 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3348 // FTEQW range #200-#299
3367 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3370 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3371 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3372 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3373 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3374 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3375 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3376 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3377 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3378 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3379 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3381 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3389 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3412 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.
3413 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
3414 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3415 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3416 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)
3417 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
3418 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)
3419 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)
3420 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)
3421 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)
3422 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)
3423 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
3424 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)
3425 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
3426 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.
3449 // CSQC range #300-#399
3450 NULL, // #300 void() clearscene (EXT_CSQC)
3451 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3452 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3453 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3454 NULL, // #304 void() renderscene (EXT_CSQC)
3455 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3456 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3457 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3458 NULL, // #308 void() R_EndPolygon
3460 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3461 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3465 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3466 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3467 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3468 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3469 NULL, // #319 void(string name) freepic (EXT_CSQC)
3470 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3471 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3472 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3473 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3474 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3475 NULL, // #325 void(void) drawresetcliparea
3480 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3481 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3482 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3483 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3484 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3485 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3486 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3487 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3488 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3489 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3490 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3491 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3492 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3493 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3494 NULL, // #344 vector() getmousepos (EXT_CSQC)
3495 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3496 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3497 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3498 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3499 NULL, // #349 float() isdemo (EXT_CSQC)
3500 VM_isserver, // #350 float() isserver (EXT_CSQC)
3501 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3502 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3503 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3504 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3510 NULL, // #360 float() readbyte (EXT_CSQC)
3511 NULL, // #361 float() readchar (EXT_CSQC)
3512 NULL, // #362 float() readshort (EXT_CSQC)
3513 NULL, // #363 float() readlong (EXT_CSQC)
3514 NULL, // #364 float() readcoord (EXT_CSQC)
3515 NULL, // #365 float() readangle (EXT_CSQC)
3516 NULL, // #366 string() readstring (EXT_CSQC)
3517 NULL, // #367 float() readfloat (EXT_CSQC)
3550 // LordHavoc's range #400-#499
3551 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3552 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3553 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3554 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3555 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3556 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3557 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3558 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3559 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)
3560 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3561 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3562 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3563 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3564 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3565 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3566 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3567 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3568 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3569 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3570 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3571 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3572 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3573 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3574 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3575 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3576 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3577 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3578 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3579 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3580 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3581 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3582 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3583 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3584 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3585 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3586 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3587 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3588 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3589 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3590 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3591 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3592 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3593 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3594 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3595 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3596 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3597 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3598 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3599 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3600 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3601 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3602 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3603 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3604 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3605 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3606 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3607 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3608 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3610 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3611 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3612 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3613 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3614 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3615 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3616 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3617 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3618 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3619 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3620 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3622 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3623 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3624 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3625 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3626 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3627 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3628 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3629 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3630 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3631 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3632 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3633 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3634 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3635 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3636 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3637 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3645 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3646 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3647 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3648 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3649 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3650 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3651 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3652 VM_SV_WritePicture, // #501
3654 VM_whichpack, // #503 string(string) whichpack = #503;
3661 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3662 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3663 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3664 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)
3665 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3666 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3667 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3668 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3669 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3670 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3680 VM_loadfromdata, // #529
3681 VM_loadfromfile, // #530
3682 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3684 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3685 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3691 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3692 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3693 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3756 VM_callfunction, // #605
3757 VM_writetofile, // #606
3758 VM_isfunction, // #607
3764 VM_parseentitydata, // #613
3775 VM_SV_getextresponse, // #624 string getextresponse(void)
3778 VM_sprintf, // #627 string sprintf(string format, ...)
3779 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3780 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3784 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3786 void VM_SV_Cmd_Init(void)
3791 void VM_SV_Cmd_Reset(void)
3793 World_End(&sv.world);
3794 if(PRVM_serverfunction(SV_Shutdown))
3796 func_t s = PRVM_serverfunction(SV_Shutdown);
3797 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3798 PRVM_ExecuteProgram(s,"SV_Shutdown() required");