6 //============================================================================
11 const char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
24 "DP_CSQC_ENTITYWORLDOBJECT "
25 "DP_CSQC_ENTITYMODELLIGHT "
26 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
27 "DP_CSQC_MULTIFRAME_INTERPOLATION "
28 "DP_CSQC_BOXPARTICLES "
29 "DP_CSQC_SPAWNPARTICLE "
30 "DP_CSQC_QUERYRENDERENTITY "
31 "DP_CSQC_ROTATEMOVES "
44 "DP_EF_RESTARTANIM_BIT "
49 "DP_ENT_CUSTOMCOLORMAP "
50 "DP_ENT_EXTERIORMODELTOCLIENT "
53 "DP_ENT_LOWPRECISION "
55 "DP_ENT_TRAILEFFECTNUM "
58 "DP_GFX_EXTERNALTEXTURES "
59 "DP_GFX_EXTERNALTEXTURES_PERMAP "
61 "DP_GFX_MODEL_INTERPOLATION "
62 "DP_GFX_QUAKE3MODELTAGS "
66 "DP_GFX_FONTS_FREETYPE "
68 "DP_FONT_VARIABLEWIDTH "
70 "DP_HALFLIFE_MAP_CVAR "
73 "DP_LIGHTSTYLE_STATICVALUE "
77 "DP_MOVETYPEBOUNCEMISSILE "
78 "DP_MOVETYPEFLYWORLDONLY "
81 "DP_QC_ASINACOSATANATAN2TAN "
87 "DP_QC_CVAR_DEFSTRING "
88 "DP_QC_CVAR_DESCRIPTION "
95 "DP_QC_EXTRESPONSEPACKET "
97 "DP_QC_FINDCHAINFLAGS "
98 "DP_QC_FINDCHAINFLOAT "
99 "DP_QC_FINDCHAIN_TOFIELD "
105 "DP_QC_GETSURFACETRIANGLE "
106 "DP_QC_GETSURFACEPOINTATTRIBUTE "
108 "DP_QC_GETTAGINFO_BONEPROPERTIES "
110 "DP_QC_GETTIME_CDTRACK "
113 "DP_QC_MULTIPLETEMPSTRINGS "
114 "DP_QC_NUM_FOR_EDICT "
116 "DP_QC_SINCOSSQRTPOW "
119 "DP_QC_STRINGBUFFERS "
120 "DP_QC_STRINGBUFFERS_CVARLIST "
121 "DP_QC_STRINGCOLORFUNCTIONS "
122 "DP_QC_STRING_CASE_FUNCTIONS "
124 "DP_QC_TOKENIZEBYSEPARATOR "
125 "DP_QC_TOKENIZE_CONSOLE "
128 "DP_QC_TRACE_MOVETYPE_HITMODEL "
129 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
130 "DP_QC_UNLIMITEDTEMPSTRINGS "
134 "DP_QC_VECTOANGLES_WITH_ROLL "
135 "DP_QC_VECTORVECTORS "
142 "DP_SKELETONOBJECTS "
143 "DP_SND_DIRECTIONLESSATTNNONE "
145 "DP_SND_SOUND7_WIP1 "
149 "DP_SND_GETSOUNDTIME "
151 "DP_VIDEO_SUBTITLES "
155 "DP_SV_BOUNCEFACTOR "
156 "DP_SV_CLIENTCAMERA "
157 "DP_SV_CLIENTCOLORS "
160 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
161 "DP_SV_DISCARDABLEDEMO "
162 "DP_SV_DRAWONLYTOCLIENT "
165 "DP_SV_ENTITYCONTENTSTRANSITION "
166 "DP_SV_MODELFLAGS_AS_EFFECTS "
167 "DP_SV_MOVETYPESTEP_LANDEVENT "
169 "DP_SV_NODRAWTOCLIENT "
170 "DP_SV_ONENTITYNOSPAWNFUNCTION "
171 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
173 "DP_SV_PING_PACKETLOSS "
174 "DP_SV_PLAYERPHYSICS "
176 "DP_SV_POINTPARTICLES "
178 "DP_SV_PRECACHEANYTIME "
182 "DP_SV_ROTATINGBMODEL "
186 "DP_SV_SPAWNFUNC_PREFIX "
187 "DP_SV_WRITEPICTURE "
188 "DP_SV_WRITEUNTERMINATEDSTRING "
192 "DP_TE_EXPLOSIONRGB "
194 "DP_TE_PARTICLECUBE "
195 "DP_TE_PARTICLERAIN "
196 "DP_TE_PARTICLESNOW "
198 "DP_TE_QUADEFFECTS1 "
201 "DP_TE_STANDARDEFFECTBUILTINS "
202 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
206 "FTE_CSQC_SKELETONOBJECTS "
209 "KRIMZON_SV_PARSECLIENTCOMMAND "
212 "NEXUIZ_PLAYERMODEL "
214 "PRYDON_CLIENTCURSOR "
215 "TENEBRAE_GFX_DLIGHTS "
218 //"EXT_CSQC " // not ready yet
225 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.
227 setorigin (entity, origin)
230 static void VM_SV_setorigin (void)
235 VM_SAFEPARMCOUNT(2, VM_setorigin);
237 e = PRVM_G_EDICT(OFS_PARM0);
238 if (e == prog->edicts)
240 VM_Warning("setorigin: can not modify world entity\n");
243 if (e->priv.server->free)
245 VM_Warning("setorigin: can not modify free entity\n");
248 org = PRVM_G_VECTOR(OFS_PARM1);
249 VectorCopy (org, PRVM_serveredictvector(e, origin));
253 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
254 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
258 for (i=0 ; i<3 ; i++)
260 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
262 // set derived values
263 VectorCopy (min, PRVM_serveredictvector(e, mins));
264 VectorCopy (max, PRVM_serveredictvector(e, maxs));
265 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
274 the size box is rotated by the current angle
275 LordHavoc: no it isn't...
277 setsize (entity, minvector, maxvector)
280 static void VM_SV_setsize (void)
285 VM_SAFEPARMCOUNT(3, VM_setsize);
287 e = PRVM_G_EDICT(OFS_PARM0);
288 if (e == prog->edicts)
290 VM_Warning("setsize: can not modify world entity\n");
293 if (e->priv.server->free)
295 VM_Warning("setsize: can not modify free entity\n");
298 min = PRVM_G_VECTOR(OFS_PARM1);
299 max = PRVM_G_VECTOR(OFS_PARM2);
300 SetMinMaxSize (e, min, max, false);
308 setmodel(entity, model)
311 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
312 static void VM_SV_setmodel (void)
318 VM_SAFEPARMCOUNT(2, VM_setmodel);
320 e = PRVM_G_EDICT(OFS_PARM0);
321 if (e == prog->edicts)
323 VM_Warning("setmodel: can not modify world entity\n");
326 if (e->priv.server->free)
328 VM_Warning("setmodel: can not modify free entity\n");
331 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
332 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
333 PRVM_serveredictfloat(e, modelindex) = i;
335 mod = SV_GetModelByIndex(i);
339 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
340 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
342 SetMinMaxSize (e, quakemins, quakemaxs, true);
345 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
352 single print to a specific client
354 sprint(clientent, value)
357 static void VM_SV_sprint (void)
361 char string[VM_STRINGTEMP_LENGTH];
363 VM_VarString(1, string, sizeof(string));
365 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
367 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
368 // LordHavoc: div0 requested that sprintto world operate like print
375 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
377 VM_Warning("tried to centerprint to a non-client\n");
381 client = svs.clients + entnum-1;
382 if (!client->netconnection)
385 MSG_WriteChar(&client->netconnection->message,svc_print);
386 MSG_WriteString(&client->netconnection->message, string);
394 single print to a specific client
396 centerprint(clientent, value)
399 static void VM_SV_centerprint (void)
403 char string[VM_STRINGTEMP_LENGTH];
405 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
407 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
409 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
411 VM_Warning("tried to centerprint to a non-client\n");
415 client = svs.clients + entnum-1;
416 if (!client->netconnection)
419 VM_VarString(1, string, sizeof(string));
420 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
421 MSG_WriteString(&client->netconnection->message, string);
428 particle(origin, color, count)
431 static void VM_SV_particle (void)
437 VM_SAFEPARMCOUNT(4, VM_SV_particle);
439 org = PRVM_G_VECTOR(OFS_PARM0);
440 dir = PRVM_G_VECTOR(OFS_PARM1);
441 color = PRVM_G_FLOAT(OFS_PARM2);
442 count = PRVM_G_FLOAT(OFS_PARM3);
443 SV_StartParticle (org, dir, (int)color, (int)count);
453 static void VM_SV_ambientsound (void)
457 float vol, attenuation;
460 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
462 pos = PRVM_G_VECTOR (OFS_PARM0);
463 samp = PRVM_G_STRING(OFS_PARM1);
464 vol = PRVM_G_FLOAT(OFS_PARM2);
465 attenuation = PRVM_G_FLOAT(OFS_PARM3);
467 // check to see if samp was properly precached
468 soundnum = SV_SoundIndex(samp, 1);
476 // add an svc_spawnambient command to the level signon packet
479 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
481 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
483 MSG_WriteVector(&sv.signon, pos, sv.protocol);
485 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
486 MSG_WriteShort (&sv.signon, soundnum);
488 MSG_WriteByte (&sv.signon, soundnum);
490 MSG_WriteByte (&sv.signon, (int)(vol*255));
491 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
499 Each entity can have eight independant sound sources, like voice,
502 Channel 0 is an auto-allocate channel, the others override anything
503 already running on that entity/channel pair.
505 An attenuation of 0 will play full volume everywhere in the level.
506 Larger attenuations will drop off.
510 static void VM_SV_sound (void)
514 prvm_edict_t *entity;
520 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
522 entity = PRVM_G_EDICT(OFS_PARM0);
523 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
524 sample = PRVM_G_STRING(OFS_PARM2);
525 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
528 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
532 attenuation = PRVM_G_FLOAT(OFS_PARM4);
536 pitchchange = PRVM_G_FLOAT(OFS_PARM5);
541 if(channel >= 8 && channel <= 15) // weird QW feature
543 flags |= CHANFLAG_RELIABLE;
548 flags = PRVM_G_FLOAT(OFS_PARM6);
550 if (volume < 0 || volume > 255)
552 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
556 if (attenuation < 0 || attenuation > 4)
558 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
562 channel = CHAN_USER2ENGINE(channel);
564 if (!IS_CHAN(channel))
566 VM_Warning("SV_StartSound: channel must be in range 0-127\n");
570 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE);
577 Follows the same logic as VM_SV_sound, except instead of
578 an entity, an origin for the sound is provided, and channel
579 is omitted (since no entity is being tracked).
583 static void VM_SV_pointsound(void)
590 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
592 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
593 sample = PRVM_G_STRING(OFS_PARM1);
594 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
595 attenuation = PRVM_G_FLOAT(OFS_PARM3);
597 if (volume < 0 || volume > 255)
599 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
603 if (attenuation < 0 || attenuation > 4)
605 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
609 SV_StartPointSound (org, sample, volume, attenuation);
616 Used for use tracing and shot targeting
617 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
618 if the tryents flag is set.
620 traceline (vector1, vector2, movetype, ignore)
623 static void VM_SV_traceline (void)
630 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
632 prog->xfunction->builtinsprofile += 30;
634 v1 = PRVM_G_VECTOR(OFS_PARM0);
635 v2 = PRVM_G_VECTOR(OFS_PARM1);
636 move = (int)PRVM_G_FLOAT(OFS_PARM2);
637 ent = PRVM_G_EDICT(OFS_PARM3);
639 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]))
640 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));
642 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
644 VM_SetTraceGlobals(&trace);
652 Used for use tracing and shot targeting
653 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
654 if the tryents flag is set.
656 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
659 // LordHavoc: added this for my own use, VERY useful, similar to traceline
660 static void VM_SV_tracebox (void)
662 float *v1, *v2, *m1, *m2;
667 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
669 prog->xfunction->builtinsprofile += 30;
671 v1 = PRVM_G_VECTOR(OFS_PARM0);
672 m1 = PRVM_G_VECTOR(OFS_PARM1);
673 m2 = PRVM_G_VECTOR(OFS_PARM2);
674 v2 = PRVM_G_VECTOR(OFS_PARM3);
675 move = (int)PRVM_G_FLOAT(OFS_PARM4);
676 ent = PRVM_G_EDICT(OFS_PARM5);
678 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]))
679 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));
681 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
683 VM_SetTraceGlobals(&trace);
686 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
691 vec3_t original_origin;
692 vec3_t original_velocity;
693 vec3_t original_angles;
694 vec3_t original_avelocity;
697 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
698 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
699 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
700 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
702 gravity = PRVM_serveredictfloat(tossent, gravity);
705 gravity *= sv_gravity.value * 0.025;
707 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
709 SV_CheckVelocity (tossent);
710 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
711 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
712 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
713 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
714 trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
715 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
716 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
718 if (trace.fraction < 1)
722 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
723 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
724 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
725 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
730 static void VM_SV_tracetoss (void)
734 prvm_edict_t *ignore;
736 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
738 prog->xfunction->builtinsprofile += 600;
740 ent = PRVM_G_EDICT(OFS_PARM0);
741 if (ent == prog->edicts)
743 VM_Warning("tracetoss: can not use world entity\n");
746 ignore = PRVM_G_EDICT(OFS_PARM1);
748 trace = SV_Trace_Toss (ent, ignore);
750 VM_SetTraceGlobals(&trace);
753 //============================================================================
755 static int checkpvsbytes;
756 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
758 static int VM_SV_newcheckclient (int check)
764 // cycle to the next one
766 check = bound(1, check, svs.maxclients);
767 if (check == svs.maxclients)
775 prog->xfunction->builtinsprofile++;
777 if (i == svs.maxclients+1)
779 // look up the client's edict
780 ent = PRVM_EDICT_NUM(i);
781 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
782 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
784 // found a valid client (possibly the same one again)
788 // get the PVS for the entity
789 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
791 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
792 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
801 Returns a client (or object that has a client enemy) that would be a
804 If there is more than one valid option, they are cycled each frame
806 If (self.origin + self.viewofs) is not in the PVS of the current target,
807 it is not returned at all.
812 int c_invis, c_notvis;
813 static void VM_SV_checkclient (void)
815 prvm_edict_t *ent, *self;
818 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
820 // find a new check if on a new frame
821 if (sv.time - sv.lastchecktime >= 0.1)
823 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
824 sv.lastchecktime = sv.time;
827 // return check if it might be visible
828 ent = PRVM_EDICT_NUM(sv.lastcheck);
829 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
831 VM_RETURN_EDICT(prog->edicts);
835 // if current entity can't possibly see the check entity, return 0
836 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
837 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
838 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
841 VM_RETURN_EDICT(prog->edicts);
845 // might be able to see it
847 VM_RETURN_EDICT(ent);
850 //============================================================================
856 Checks if an entity is in a point's PVS.
857 Should be fast but can be inexact.
859 float checkpvs(vector viewpos, entity viewee) = #240;
862 static void VM_SV_checkpvs (void)
865 prvm_edict_t *viewee;
870 unsigned char fatpvs[MAX_MAP_LEAFS/8];
873 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
874 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
875 viewee = PRVM_G_EDICT(OFS_PARM1);
877 if(viewee->priv.server->free)
879 VM_Warning("checkpvs: can not check free entity\n");
880 PRVM_G_FLOAT(OFS_RETURN) = 4;
885 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
887 // no PVS support on this worldmodel... darn
888 PRVM_G_FLOAT(OFS_RETURN) = 3;
891 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
894 // viewpos isn't in any PVS... darn
895 PRVM_G_FLOAT(OFS_RETURN) = 2;
898 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
900 // using fat PVS like FTEQW does (slow)
901 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
903 // no PVS support on this worldmodel... darn
904 PRVM_G_FLOAT(OFS_RETURN) = 3;
907 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
910 // viewpos isn't in any PVS... darn
911 PRVM_G_FLOAT(OFS_RETURN) = 2;
914 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
923 Sends text over to the client's execution buffer
925 stuffcmd (clientent, value, ...)
928 static void VM_SV_stuffcmd (void)
932 char string[VM_STRINGTEMP_LENGTH];
934 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
936 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
937 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
939 VM_Warning("Can't stuffcmd to a non-client\n");
943 VM_VarString(1, string, sizeof(string));
946 host_client = svs.clients + entnum-1;
947 Host_ClientCommands ("%s", string);
955 Returns a chain of entities that have origins within a spherical area
957 findradius (origin, radius)
960 static void VM_SV_findradius (void)
962 prvm_edict_t *ent, *chain;
963 vec_t radius, radius2;
964 vec3_t org, eorg, mins, maxs;
967 static prvm_edict_t *touchedicts[MAX_EDICTS];
970 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
973 chainfield = PRVM_G_INT(OFS_PARM2);
975 chainfield = prog->fieldoffsets.chain;
977 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
979 chain = (prvm_edict_t *)prog->edicts;
981 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
982 radius = PRVM_G_FLOAT(OFS_PARM1);
983 radius2 = radius * radius;
985 mins[0] = org[0] - (radius + 1);
986 mins[1] = org[1] - (radius + 1);
987 mins[2] = org[2] - (radius + 1);
988 maxs[0] = org[0] + (radius + 1);
989 maxs[1] = org[1] + (radius + 1);
990 maxs[2] = org[2] + (radius + 1);
991 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
992 if (numtouchedicts > MAX_EDICTS)
994 // this never happens
995 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
996 numtouchedicts = MAX_EDICTS;
998 for (i = 0;i < numtouchedicts;i++)
1000 ent = touchedicts[i];
1001 prog->xfunction->builtinsprofile++;
1002 // Quake did not return non-solid entities but darkplaces does
1003 // (note: this is the reason you can't blow up fallen zombies)
1004 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1006 // LordHavoc: compare against bounding box rather than center so it
1007 // doesn't miss large objects, and use DotProduct instead of Length
1008 // for a major speedup
1009 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1010 if (sv_gameplayfix_findradiusdistancetobox.integer)
1012 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1013 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1014 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1017 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1018 if (DotProduct(eorg, eorg) < radius2)
1020 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1025 VM_RETURN_EDICT(chain);
1028 static void VM_SV_precache_sound (void)
1030 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1031 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1034 static void VM_SV_precache_model (void)
1036 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1037 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1038 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1045 float(float yaw, float dist[, settrace]) walkmove
1048 static void VM_SV_walkmove (void)
1057 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1059 // assume failure if it returns early
1060 PRVM_G_FLOAT(OFS_RETURN) = 0;
1062 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1063 if (ent == prog->edicts)
1065 VM_Warning("walkmove: can not modify world entity\n");
1068 if (ent->priv.server->free)
1070 VM_Warning("walkmove: can not modify free entity\n");
1073 yaw = PRVM_G_FLOAT(OFS_PARM0);
1074 dist = PRVM_G_FLOAT(OFS_PARM1);
1075 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1077 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1080 yaw = yaw*M_PI*2 / 360;
1082 move[0] = cos(yaw)*dist;
1083 move[1] = sin(yaw)*dist;
1086 // save program state, because SV_movestep may call other progs
1087 oldf = prog->xfunction;
1088 oldself = PRVM_serverglobaledict(self);
1090 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1093 // restore program state
1094 prog->xfunction = oldf;
1095 PRVM_serverglobaledict(self) = oldself;
1106 static void VM_SV_droptofloor (void)
1112 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1114 // assume failure if it returns early
1115 PRVM_G_FLOAT(OFS_RETURN) = 0;
1117 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1118 if (ent == prog->edicts)
1120 VM_Warning("droptofloor: can not modify world entity\n");
1123 if (ent->priv.server->free)
1125 VM_Warning("droptofloor: can not modify free entity\n");
1129 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1132 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1133 if (sv_gameplayfix_unstickentities.integer)
1134 SV_UnstickEntity(ent);
1136 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1137 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1140 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]);
1141 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1142 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1143 VectorSubtract(trace.endpos, offset, trace.endpos);
1144 if (trace.startsolid)
1146 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]);
1147 if (sv_gameplayfix_unstickentities.integer)
1148 SV_UnstickEntity(ent);
1150 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1151 PRVM_serveredictedict(ent, groundentity) = 0;
1152 PRVM_G_FLOAT(OFS_RETURN) = 1;
1154 else if (trace.fraction < 1)
1156 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]);
1157 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1158 if (sv_gameplayfix_unstickentities.integer)
1159 SV_UnstickEntity(ent);
1161 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1162 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1163 PRVM_G_FLOAT(OFS_RETURN) = 1;
1164 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1165 ent->priv.server->suspendedinairflag = true;
1170 if (trace.fraction != 1)
1172 if (trace.fraction < 1)
1173 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1175 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1176 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1177 PRVM_G_FLOAT(OFS_RETURN) = 1;
1178 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1179 ent->priv.server->suspendedinairflag = true;
1188 void(float style, string value) lightstyle
1191 static void VM_SV_lightstyle (void)
1198 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1200 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1201 val = PRVM_G_STRING(OFS_PARM1);
1203 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1204 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1207 // change the string in sv
1208 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1210 // send message to all clients on this server
1211 if (sv.state != ss_active)
1214 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1216 if (client->active && client->netconnection)
1218 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1219 MSG_WriteChar (&client->netconnection->message,style);
1220 MSG_WriteString (&client->netconnection->message, val);
1230 static void VM_SV_checkbottom (void)
1232 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1233 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1241 static void VM_SV_pointcontents (void)
1243 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1244 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1251 Pick a vector for the player to shoot along
1252 vector aim(entity, missilespeed)
1255 static void VM_SV_aim (void)
1257 prvm_edict_t *ent, *check, *bestent;
1258 vec3_t start, dir, end, bestdir;
1261 float dist, bestdist;
1264 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1266 // assume failure if it returns early
1267 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1268 // if sv_aim is so high it can't possibly accept anything, skip out early
1269 if (sv_aim.value >= 1)
1272 ent = PRVM_G_EDICT(OFS_PARM0);
1273 if (ent == prog->edicts)
1275 VM_Warning("aim: can not use world entity\n");
1278 if (ent->priv.server->free)
1280 VM_Warning("aim: can not use free entity\n");
1283 //speed = PRVM_G_FLOAT(OFS_PARM1);
1285 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1288 // try sending a trace straight
1289 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1290 VectorMA (start, 2048, dir, end);
1291 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1292 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1293 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1295 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1300 // try all possible entities
1301 VectorCopy (dir, bestdir);
1302 bestdist = sv_aim.value;
1305 check = PRVM_NEXT_EDICT(prog->edicts);
1306 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1308 prog->xfunction->builtinsprofile++;
1309 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1313 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1314 continue; // don't aim at teammate
1315 for (j=0 ; j<3 ; j++)
1316 end[j] = PRVM_serveredictvector(check, origin)[j]
1317 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1318 VectorSubtract (end, start, dir);
1319 VectorNormalize (dir);
1320 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1321 if (dist < bestdist)
1322 continue; // to far to turn
1323 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1324 if (tr.ent == check)
1325 { // can shoot at this one
1333 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1334 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1335 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1337 VectorNormalize (end);
1338 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1342 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1347 ===============================================================================
1351 ===============================================================================
1354 #define MSG_BROADCAST 0 // unreliable to all
1355 #define MSG_ONE 1 // reliable to one (msg_entity)
1356 #define MSG_ALL 2 // reliable to all
1357 #define MSG_INIT 3 // write to the init string
1358 #define MSG_ENTITY 5
1360 sizebuf_t *WriteDest (void)
1366 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1370 return &sv.datagram;
1373 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1374 entnum = PRVM_NUM_FOR_EDICT(ent);
1375 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1377 VM_Warning ("WriteDest: tried to write to non-client\n");
1378 return &sv.reliable_datagram;
1381 return &svs.clients[entnum-1].netconnection->message;
1384 VM_Warning ("WriteDest: bad destination\n");
1386 return &sv.reliable_datagram;
1392 return sv.writeentitiestoclient_msg;
1398 static void VM_SV_WriteByte (void)
1400 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1401 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1404 static void VM_SV_WriteChar (void)
1406 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1407 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1410 static void VM_SV_WriteShort (void)
1412 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1413 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1416 static void VM_SV_WriteLong (void)
1418 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1419 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1422 static void VM_SV_WriteAngle (void)
1424 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1425 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1428 static void VM_SV_WriteCoord (void)
1430 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1431 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1434 static void VM_SV_WriteString (void)
1436 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1437 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1440 static void VM_SV_WriteUnterminatedString (void)
1442 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1443 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1447 static void VM_SV_WriteEntity (void)
1449 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1450 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1453 // writes a picture as at most size bytes of data
1455 // IMGNAME \0 SIZE(short) IMGDATA
1456 // if failed to read/compress:
1458 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1459 static void VM_SV_WritePicture (void)
1461 const char *imgname;
1465 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1467 imgname = PRVM_G_STRING(OFS_PARM1);
1468 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1472 MSG_WriteString(WriteDest(), imgname);
1473 if(Image_Compress(imgname, size, &buf, &size))
1476 MSG_WriteShort(WriteDest(), size);
1477 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1482 MSG_WriteShort(WriteDest(), 0);
1486 //////////////////////////////////////////////////////////
1488 static void VM_SV_makestatic (void)
1493 // allow 0 parameters due to an id1 qc bug in which this function is used
1494 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1495 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1497 if (prog->argc >= 1)
1498 ent = PRVM_G_EDICT(OFS_PARM0);
1500 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1501 if (ent == prog->edicts)
1503 VM_Warning("makestatic: can not modify world entity\n");
1506 if (ent->priv.server->free)
1508 VM_Warning("makestatic: can not modify free entity\n");
1513 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1518 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1519 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1520 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1522 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1524 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1525 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1526 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1530 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1531 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1532 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1535 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1536 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1537 for (i=0 ; i<3 ; i++)
1539 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1540 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1543 // throw the entity away now
1547 //=============================================================================
1554 static void VM_SV_setspawnparms (void)
1560 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1562 ent = PRVM_G_EDICT(OFS_PARM0);
1563 i = PRVM_NUM_FOR_EDICT(ent);
1564 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1566 Con_Print("tried to setspawnparms on a non-client\n");
1570 // copy spawn parms out of the client_t
1571 client = svs.clients + i-1;
1572 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1573 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1580 Returns a color vector indicating the lighting at the requested point.
1582 (Internal Operation note: actually measures the light beneath the point, just like
1583 the model lighting on the client)
1588 static void VM_SV_getlight (void)
1590 vec3_t ambientcolor, diffusecolor, diffusenormal;
1592 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1593 p = PRVM_G_VECTOR(OFS_PARM0);
1594 VectorClear(ambientcolor);
1595 VectorClear(diffusecolor);
1596 VectorClear(diffusenormal);
1597 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1598 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1599 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1604 unsigned char type; // 1/2/8 or other value if isn't used
1608 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1609 static int vm_customstats_last;
1611 void VM_CustomStats_Clear (void)
1615 Z_Free(vm_customstats);
1616 vm_customstats = NULL;
1617 vm_customstats_last = -1;
1621 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1629 for(i=0; i<vm_customstats_last+1 ;i++)
1631 if(!vm_customstats[i].type)
1633 switch(vm_customstats[i].type)
1635 //string as 16 bytes
1638 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1639 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1640 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1641 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1642 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1644 //float field sent as-is
1646 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1648 //integer value of float field
1650 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1658 // void(float index, float type, .void field) SV_AddStat = #232;
1659 // Set up an auto-sent player stat.
1660 // Client's get thier own fields sent to them. Index may not be less than 32.
1661 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1662 // 1: string (4 stats carrying a total of 16 charactures)
1663 // 2: float (one stat, float converted to an integer for transportation)
1664 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1665 static void VM_SV_AddStat (void)
1670 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1674 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1677 VM_Warning("PF_SV_AddStat: not enough memory\n");
1681 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1682 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1683 off = PRVM_G_INT (OFS_PARM2);
1688 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1691 if(i >= (MAX_CL_STATS-32))
1693 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1696 if(i > (MAX_CL_STATS-32-4) && type == 1)
1698 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1701 vm_customstats[i].type = type;
1702 vm_customstats[i].fieldoffset = off;
1703 if(vm_customstats_last < i)
1704 vm_customstats_last = i;
1711 copies data from one entity to another
1713 copyentity(src, dst)
1716 static void VM_SV_copyentity (void)
1718 prvm_edict_t *in, *out;
1719 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1720 in = PRVM_G_EDICT(OFS_PARM0);
1721 if (in == prog->edicts)
1723 VM_Warning("copyentity: can not read world entity\n");
1726 if (in->priv.server->free)
1728 VM_Warning("copyentity: can not read free entity\n");
1731 out = PRVM_G_EDICT(OFS_PARM1);
1732 if (out == prog->edicts)
1734 VM_Warning("copyentity: can not modify world entity\n");
1737 if (out->priv.server->free)
1739 VM_Warning("copyentity: can not modify free entity\n");
1742 memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
1751 sets the color of a client and broadcasts the update to all connected clients
1753 setcolor(clientent, value)
1756 static void VM_SV_setcolor (void)
1761 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1762 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1763 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1765 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1767 Con_Print("tried to setcolor a non-client\n");
1771 client = svs.clients + entnum-1;
1774 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1775 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1778 if (client->old_colors != client->colors)
1780 client->old_colors = client->colors;
1781 // send notification to all clients
1782 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1783 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1784 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1792 effect(origin, modelname, startframe, framecount, framerate)
1795 static void VM_SV_effect (void)
1799 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1800 s = PRVM_G_STRING(OFS_PARM1);
1803 VM_Warning("effect: no model specified\n");
1807 i = SV_ModelIndex(s, 1);
1810 VM_Warning("effect: model not precached\n");
1814 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1816 VM_Warning("effect: framecount < 1\n");
1820 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1822 VM_Warning("effect: framerate < 1\n");
1826 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));
1829 static void VM_SV_te_blood (void)
1831 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1832 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1834 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1835 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1837 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1838 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1839 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1841 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1842 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1843 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1845 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1846 SV_FlushBroadcastMessages();
1849 static void VM_SV_te_bloodshower (void)
1851 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1852 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1854 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1855 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1857 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1858 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1859 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1861 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1862 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1863 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1865 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1867 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1868 SV_FlushBroadcastMessages();
1871 static void VM_SV_te_explosionrgb (void)
1873 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1874 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1875 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1877 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1878 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1879 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1881 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1882 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1883 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1884 SV_FlushBroadcastMessages();
1887 static void VM_SV_te_particlecube (void)
1889 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1890 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1892 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1893 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1895 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1896 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1900 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1907 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1909 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1910 // gravity true/false
1911 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1913 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1914 SV_FlushBroadcastMessages();
1917 static void VM_SV_te_particlerain (void)
1919 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1920 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1922 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1923 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1925 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1926 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1934 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1937 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1939 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1940 SV_FlushBroadcastMessages();
1943 static void VM_SV_te_particlesnow (void)
1945 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1946 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1948 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1949 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1952 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1953 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1955 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1963 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1965 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1966 SV_FlushBroadcastMessages();
1969 static void VM_SV_te_spark (void)
1971 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1972 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1974 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1975 MSG_WriteByte(&sv.datagram, TE_SPARK);
1977 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1978 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1979 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1981 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1982 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1983 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1985 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1986 SV_FlushBroadcastMessages();
1989 static void VM_SV_te_gunshotquad (void)
1991 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1992 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1993 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1995 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1996 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1997 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1998 SV_FlushBroadcastMessages();
2001 static void VM_SV_te_spikequad (void)
2003 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2004 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2005 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2007 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2008 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2009 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2010 SV_FlushBroadcastMessages();
2013 static void VM_SV_te_superspikequad (void)
2015 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2016 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2017 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2019 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2020 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2021 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2022 SV_FlushBroadcastMessages();
2025 static void VM_SV_te_explosionquad (void)
2027 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2028 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2029 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2031 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2032 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2033 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2034 SV_FlushBroadcastMessages();
2037 static void VM_SV_te_smallflash (void)
2039 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2040 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2041 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2043 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2044 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2045 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2046 SV_FlushBroadcastMessages();
2049 static void VM_SV_te_customflash (void)
2051 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2052 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2054 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2055 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2058 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2059 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2061 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2063 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2065 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2066 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2067 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2068 SV_FlushBroadcastMessages();
2071 static void VM_SV_te_gunshot (void)
2073 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2074 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2075 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2077 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2078 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2079 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2080 SV_FlushBroadcastMessages();
2083 static void VM_SV_te_spike (void)
2085 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2086 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2087 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2089 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2090 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2091 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2092 SV_FlushBroadcastMessages();
2095 static void VM_SV_te_superspike (void)
2097 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2098 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2099 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2101 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2102 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2103 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2104 SV_FlushBroadcastMessages();
2107 static void VM_SV_te_explosion (void)
2109 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2110 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2111 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2113 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2114 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2115 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2116 SV_FlushBroadcastMessages();
2119 static void VM_SV_te_tarexplosion (void)
2121 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2122 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2123 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2125 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2126 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2127 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2128 SV_FlushBroadcastMessages();
2131 static void VM_SV_te_wizspike (void)
2133 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2134 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2135 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2137 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2138 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2139 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2140 SV_FlushBroadcastMessages();
2143 static void VM_SV_te_knightspike (void)
2145 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2146 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2147 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2149 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2150 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2151 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2152 SV_FlushBroadcastMessages();
2155 static void VM_SV_te_lavasplash (void)
2157 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2158 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2159 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2161 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2162 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2163 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2164 SV_FlushBroadcastMessages();
2167 static void VM_SV_te_teleport (void)
2169 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2170 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2171 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2173 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2174 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2175 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2176 SV_FlushBroadcastMessages();
2179 static void VM_SV_te_explosion2 (void)
2181 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2182 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2183 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2185 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2186 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2187 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2189 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2190 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2191 SV_FlushBroadcastMessages();
2194 static void VM_SV_te_lightning1 (void)
2196 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2197 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2198 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2200 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2202 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2203 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2204 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2206 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2207 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2208 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2209 SV_FlushBroadcastMessages();
2212 static void VM_SV_te_lightning2 (void)
2214 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2215 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2216 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2218 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2220 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2221 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2222 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2224 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2225 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2226 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2227 SV_FlushBroadcastMessages();
2230 static void VM_SV_te_lightning3 (void)
2232 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2233 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2234 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2236 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2238 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2239 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2240 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2242 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2243 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2244 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2245 SV_FlushBroadcastMessages();
2248 static void VM_SV_te_beam (void)
2250 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2251 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2252 MSG_WriteByte(&sv.datagram, TE_BEAM);
2254 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2256 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2257 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2258 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2260 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2261 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2262 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2263 SV_FlushBroadcastMessages();
2266 static void VM_SV_te_plasmaburn (void)
2268 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2269 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2270 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2271 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2272 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2273 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2274 SV_FlushBroadcastMessages();
2277 static void VM_SV_te_flamejet (void)
2279 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2280 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2281 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2283 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2284 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2285 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2287 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2288 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2289 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2291 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2292 SV_FlushBroadcastMessages();
2295 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2296 //this function originally written by KrimZon, made shorter by LordHavoc
2297 static void VM_SV_clientcommand (void)
2299 client_t *temp_client;
2301 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2303 //find client for this entity
2304 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2305 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2307 Con_Print("PF_clientcommand: entity is not a client\n");
2311 temp_client = host_client;
2312 host_client = svs.clients + i;
2313 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2314 host_client = temp_client;
2317 //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)
2318 static void VM_SV_setattachment (void)
2320 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2321 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2322 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2325 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2327 if (e == prog->edicts)
2329 VM_Warning("setattachment: can not modify world entity\n");
2332 if (e->priv.server->free)
2334 VM_Warning("setattachment: can not modify free entity\n");
2338 if (tagentity == NULL)
2339 tagentity = prog->edicts;
2343 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2345 model = SV_GetModelFromEdict(tagentity);
2348 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2350 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);
2353 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));
2356 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2357 PRVM_serveredictfloat(e, tag_index) = tagindex;
2360 /////////////////////////////////////////
2361 // DP_MD3_TAGINFO extension coded by VorteX
2363 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2367 i = (int)PRVM_serveredictfloat(e, modelindex);
2368 if (i < 1 || i >= MAX_MODELS)
2371 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2374 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2381 Matrix4x4_CreateIdentity(tag_localmatrix);
2383 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2385 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2396 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2399 float pitchsign = 1;
2401 scale = PRVM_serveredictfloat(ent, scale);
2406 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);
2409 pitchsign = SV_GetPitchSign(ent);
2410 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);
2414 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2417 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2419 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2420 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2421 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2422 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2424 *out = identitymatrix;
2428 // Warnings/errors code:
2429 // 0 - normal (everything all-right)
2432 // 3 - null or non-precached model
2433 // 4 - no tags with requested index
2434 // 5 - runaway loop at attachment chain
2435 extern cvar_t cl_bob;
2436 extern cvar_t cl_bobcycle;
2437 extern cvar_t cl_bobup;
2438 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2441 int modelindex, attachloop;
2442 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2445 *out = identitymatrix; // warnings and errors return identical matrix
2447 if (ent == prog->edicts)
2449 if (ent->priv.server->free)
2452 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2453 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2456 model = SV_GetModelByIndex(modelindex);
2458 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2459 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2460 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2462 tagmatrix = identitymatrix;
2463 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2467 if (attachloop >= 256) // prevent runaway looping
2469 // apply transformation by child's tagindex on parent entity and then
2470 // by parent entity itself
2471 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2472 if (ret && attachloop == 0)
2474 SV_GetEntityMatrix(ent, &entitymatrix, false);
2475 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2476 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2477 // next iteration we process the parent entity
2478 if (PRVM_serveredictedict(ent, tag_entity))
2480 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2481 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2488 // RENDER_VIEWMODEL magic
2489 if (PRVM_serveredictedict(ent, viewmodelforclient))
2491 Matrix4x4_Copy(&tagmatrix, out);
2492 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2494 SV_GetEntityMatrix(ent, &entitymatrix, true);
2495 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2498 // Cl_bob, ported from rendering code
2499 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2502 // LordHavoc: this code is *weird*, but not replacable (I think it
2503 // should be done in QC on the server, but oh well, quake is quake)
2504 // LordHavoc: figured out bobup: the time at which the sin is at 180
2505 // degrees (which allows lengthening or squishing the peak or valley)
2506 cycle = sv.time/cl_bobcycle.value;
2507 cycle -= (int)cycle;
2508 if (cycle < cl_bobup.value)
2509 cycle = sin(M_PI * cycle / cl_bobup.value);
2511 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2512 // bob is proportional to velocity in the xy plane
2513 // (don't count Z, or jumping messes it up)
2514 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;
2515 bob = bob*0.3 + bob*0.7*cycle;
2516 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2523 //float(entity ent, string tagname) gettagindex;
2525 static void VM_SV_gettagindex (void)
2528 const char *tag_name;
2531 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2533 ent = PRVM_G_EDICT(OFS_PARM0);
2534 tag_name = PRVM_G_STRING(OFS_PARM1);
2536 if (ent == prog->edicts)
2538 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2541 if (ent->priv.server->free)
2543 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2548 if (!SV_GetModelFromEdict(ent))
2549 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2552 tag_index = SV_GetTagIndex(ent, tag_name);
2554 if(developer_extra.integer)
2555 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2557 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2560 //vector(entity ent, float tagindex) gettaginfo;
2561 static void VM_SV_gettaginfo (void)
2565 matrix4x4_t tag_matrix;
2566 matrix4x4_t tag_localmatrix;
2568 const char *tagname;
2570 vec3_t fo, le, up, trans;
2571 const dp_model_t *model;
2573 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2575 e = PRVM_G_EDICT(OFS_PARM0);
2576 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2578 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2579 Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
2580 VectorScale(le, -1, PRVM_serverglobalvector(v_right));
2581 model = SV_GetModelFromEdict(e);
2582 VM_GenerateFrameGroupBlend(e->priv.server->framegroupblend, e);
2583 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
2584 VM_UpdateEdictSkeleton(e, model, e->priv.server->frameblend);
2585 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2586 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2588 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2589 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(tagname) : 0;
2590 VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
2591 VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
2592 VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
2593 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2598 VM_Warning("gettagindex: can't affect world entity\n");
2601 VM_Warning("gettagindex: can't affect free entity\n");
2604 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2607 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2610 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2615 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2616 static void VM_SV_dropclient (void)
2619 client_t *oldhostclient;
2620 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2621 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2622 if (clientnum < 0 || clientnum >= svs.maxclients)
2624 VM_Warning("dropclient: not a client\n");
2627 if (!svs.clients[clientnum].active)
2629 VM_Warning("dropclient: that client slot is not connected\n");
2632 oldhostclient = host_client;
2633 host_client = svs.clients + clientnum;
2634 SV_DropClient(false);
2635 host_client = oldhostclient;
2638 //entity() spawnclient (DP_SV_BOTCLIENT)
2639 static void VM_SV_spawnclient (void)
2643 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2644 prog->xfunction->builtinsprofile += 2;
2646 for (i = 0;i < svs.maxclients;i++)
2648 if (!svs.clients[i].active)
2650 prog->xfunction->builtinsprofile += 100;
2651 SV_ConnectClient (i, NULL);
2652 // this has to be set or else ClientDisconnect won't be called
2653 // we assume the qc will call ClientConnect...
2654 svs.clients[i].clientconnectcalled = true;
2655 ed = PRVM_EDICT_NUM(i + 1);
2659 VM_RETURN_EDICT(ed);
2662 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2663 static void VM_SV_clienttype (void)
2666 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2667 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2668 if (clientnum < 0 || clientnum >= svs.maxclients)
2669 PRVM_G_FLOAT(OFS_RETURN) = 3;
2670 else if (!svs.clients[clientnum].active)
2671 PRVM_G_FLOAT(OFS_RETURN) = 0;
2672 else if (svs.clients[clientnum].netconnection)
2673 PRVM_G_FLOAT(OFS_RETURN) = 1;
2675 PRVM_G_FLOAT(OFS_RETURN) = 2;
2682 string(string key) serverkey
2685 void VM_SV_serverkey(void)
2687 char string[VM_STRINGTEMP_LENGTH];
2688 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2689 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2690 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2693 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2694 static void VM_SV_setmodelindex (void)
2699 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2701 e = PRVM_G_EDICT(OFS_PARM0);
2702 if (e == prog->edicts)
2704 VM_Warning("setmodelindex: can not modify world entity\n");
2707 if (e->priv.server->free)
2709 VM_Warning("setmodelindex: can not modify free entity\n");
2712 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2713 if (i <= 0 || i >= MAX_MODELS)
2715 VM_Warning("setmodelindex: invalid modelindex\n");
2718 if (!sv.model_precache[i][0])
2720 VM_Warning("setmodelindex: model not precached\n");
2724 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
2725 PRVM_serveredictfloat(e, modelindex) = i;
2727 mod = SV_GetModelByIndex(i);
2731 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2732 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2734 SetMinMaxSize (e, quakemins, quakemaxs, true);
2737 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2740 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2741 static void VM_SV_modelnameforindex (void)
2744 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2746 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2748 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2749 if (i <= 0 || i >= MAX_MODELS)
2751 VM_Warning("modelnameforindex: invalid modelindex\n");
2754 if (!sv.model_precache[i][0])
2756 VM_Warning("modelnameforindex: model not precached\n");
2760 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2763 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2764 static void VM_SV_particleeffectnum (void)
2767 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2768 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2771 PRVM_G_FLOAT(OFS_RETURN) = i;
2774 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2775 static void VM_SV_trailparticles (void)
2777 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2779 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2782 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2783 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2784 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2785 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2786 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2787 SV_FlushBroadcastMessages();
2790 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2791 static void VM_SV_pointparticles (void)
2793 int effectnum, count;
2795 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2797 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2800 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2801 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2802 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2803 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2804 if (count == 1 && !VectorLength2(vel))
2807 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2808 MSG_WriteShort(&sv.datagram, effectnum);
2809 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2813 // 1+2+12+12+2=29 bytes
2814 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2815 MSG_WriteShort(&sv.datagram, effectnum);
2816 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2817 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2818 MSG_WriteShort(&sv.datagram, count);
2821 SV_FlushBroadcastMessages();
2824 //PF_setpause, // void(float pause) setpause = #531;
2825 static void VM_SV_setpause(void) {
2827 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2828 if (pauseValue != 0) { //pause the game
2830 sv.pausedstart = Sys_DoubleTime();
2831 } else { //disable pause, in case it was enabled
2832 if (sv.paused != 0) {
2837 // send notification to all clients
2838 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2839 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2842 // #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.
2843 static void VM_SV_skel_create(void)
2845 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2846 dp_model_t *model = SV_GetModelByIndex(modelindex);
2847 skeleton_t *skeleton;
2849 PRVM_G_FLOAT(OFS_RETURN) = 0;
2850 if (!model || !model->num_bones)
2852 for (i = 0;i < MAX_EDICTS;i++)
2853 if (!prog->skeletons[i])
2855 if (i == MAX_EDICTS)
2857 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2858 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2859 skeleton->model = model;
2860 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2861 // initialize to identity matrices
2862 for (i = 0;i < skeleton->model->num_bones;i++)
2863 skeleton->relativetransforms[i] = identitymatrix;
2866 // #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
2867 static void VM_SV_skel_build(void)
2869 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2870 skeleton_t *skeleton;
2871 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2872 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2873 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2874 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2875 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2876 dp_model_t *model = SV_GetModelByIndex(modelindex);
2881 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2882 frameblend_t frameblend[MAX_FRAMEBLENDS];
2883 matrix4x4_t blendedmatrix;
2885 PRVM_G_FLOAT(OFS_RETURN) = 0;
2886 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2888 firstbone = max(0, firstbone);
2889 lastbone = min(lastbone, model->num_bones - 1);
2890 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2891 VM_GenerateFrameGroupBlend(framegroupblend, ed);
2892 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
2893 blendfrac = 1.0f - retainfrac;
2894 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2895 frameblend[numblends].lerp *= blendfrac;
2896 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2898 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2899 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2900 for (blendindex = 0;blendindex < numblends;blendindex++)
2902 Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2903 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2905 skeleton->relativetransforms[bonenum] = blendedmatrix;
2907 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2910 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2911 static void VM_SV_skel_get_numbones(void)
2913 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2914 skeleton_t *skeleton;
2915 PRVM_G_FLOAT(OFS_RETURN) = 0;
2916 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2918 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2921 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2922 static void VM_SV_skel_get_bonename(void)
2924 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2925 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2926 skeleton_t *skeleton;
2927 PRVM_G_INT(OFS_RETURN) = 0;
2928 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2930 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2932 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(skeleton->model->data_bones[bonenum].name);
2935 // #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)
2936 static void VM_SV_skel_get_boneparent(void)
2938 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2939 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2940 skeleton_t *skeleton;
2941 PRVM_G_FLOAT(OFS_RETURN) = 0;
2942 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2944 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2946 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2949 // #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
2950 static void VM_SV_skel_find_bone(void)
2952 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2953 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2954 skeleton_t *skeleton;
2955 PRVM_G_FLOAT(OFS_RETURN) = 0;
2956 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2958 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2961 // #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)
2962 static void VM_SV_skel_get_bonerel(void)
2964 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2965 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2966 skeleton_t *skeleton;
2968 vec3_t forward, left, up, origin;
2969 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2970 VectorClear(PRVM_clientglobalvector(v_forward));
2971 VectorClear(PRVM_clientglobalvector(v_right));
2972 VectorClear(PRVM_clientglobalvector(v_up));
2973 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2975 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2977 matrix = skeleton->relativetransforms[bonenum];
2978 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2979 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2980 VectorNegate(left, PRVM_clientglobalvector(v_right));
2981 VectorCopy(up, PRVM_clientglobalvector(v_up));
2982 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2985 // #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)
2986 static void VM_SV_skel_get_boneabs(void)
2988 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2989 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2990 skeleton_t *skeleton;
2993 vec3_t forward, left, up, origin;
2994 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2995 VectorClear(PRVM_clientglobalvector(v_forward));
2996 VectorClear(PRVM_clientglobalvector(v_right));
2997 VectorClear(PRVM_clientglobalvector(v_up));
2998 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3000 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3002 matrix = skeleton->relativetransforms[bonenum];
3003 // convert to absolute
3004 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3007 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3009 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3010 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3011 VectorNegate(left, PRVM_clientglobalvector(v_right));
3012 VectorCopy(up, PRVM_clientglobalvector(v_up));
3013 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3016 // #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)
3017 static void VM_SV_skel_set_bone(void)
3019 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3020 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3021 vec3_t forward, left, up, origin;
3022 skeleton_t *skeleton;
3024 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3026 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3028 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3029 VectorNegate(PRVM_clientglobalvector(v_right), left);
3030 VectorCopy(PRVM_clientglobalvector(v_up), up);
3031 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3032 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3033 skeleton->relativetransforms[bonenum] = matrix;
3036 // #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)
3037 static void VM_SV_skel_mul_bone(void)
3039 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3040 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3041 vec3_t forward, left, up, origin;
3042 skeleton_t *skeleton;
3045 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3047 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3049 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3050 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3051 VectorNegate(PRVM_clientglobalvector(v_right), left);
3052 VectorCopy(PRVM_clientglobalvector(v_up), up);
3053 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3054 temp = skeleton->relativetransforms[bonenum];
3055 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3058 // #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)
3059 static void VM_SV_skel_mul_bones(void)
3061 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3062 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3063 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3065 vec3_t forward, left, up, origin;
3066 skeleton_t *skeleton;
3069 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3071 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3072 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3073 VectorNegate(PRVM_clientglobalvector(v_right), left);
3074 VectorCopy(PRVM_clientglobalvector(v_up), up);
3075 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3076 firstbone = max(0, firstbone);
3077 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3078 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3080 temp = skeleton->relativetransforms[bonenum];
3081 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3085 // #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
3086 static void VM_SV_skel_copybones(void)
3088 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3089 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3090 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3091 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3093 skeleton_t *skeletondst;
3094 skeleton_t *skeletonsrc;
3095 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3097 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3099 firstbone = max(0, firstbone);
3100 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3101 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3102 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3103 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3106 // #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)
3107 static void VM_SV_skel_delete(void)
3109 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3110 skeleton_t *skeleton;
3111 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3114 prog->skeletons[skeletonindex] = NULL;
3117 // #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
3118 static void VM_SV_frameforname(void)
3120 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3121 dp_model_t *model = SV_GetModelByIndex(modelindex);
3122 const char *name = PRVM_G_STRING(OFS_PARM1);
3124 PRVM_G_FLOAT(OFS_RETURN) = -1;
3125 if (!model || !model->animscenes)
3127 for (i = 0;i < model->numframes;i++)
3129 if (!strcasecmp(model->animscenes[i].name, name))
3131 PRVM_G_FLOAT(OFS_RETURN) = i;
3137 // #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.
3138 static void VM_SV_frameduration(void)
3140 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3141 dp_model_t *model = SV_GetModelByIndex(modelindex);
3142 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3143 PRVM_G_FLOAT(OFS_RETURN) = 0;
3144 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3146 if (model->animscenes[framenum].framerate)
3147 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3151 prvm_builtin_t vm_sv_builtins[] = {
3152 NULL, // #0 NULL function (not callable) (QUAKE)
3153 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3154 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3155 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3156 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3157 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3158 VM_break, // #6 void() break (QUAKE)
3159 VM_random, // #7 float() random (QUAKE)
3160 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3161 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3162 VM_error, // #10 void(string e) error (QUAKE)
3163 VM_objerror, // #11 void(string e) objerror (QUAKE)
3164 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3165 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3166 VM_spawn, // #14 entity() spawn (QUAKE)
3167 VM_remove, // #15 void(entity e) remove (QUAKE)
3168 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3169 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3170 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3171 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3172 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3173 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3174 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3175 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3176 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3177 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3178 VM_ftos, // #26 string(float f) ftos (QUAKE)
3179 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3180 VM_coredump, // #28 void() coredump (QUAKE)
3181 VM_traceon, // #29 void() traceon (QUAKE)
3182 VM_traceoff, // #30 void() traceoff (QUAKE)
3183 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3184 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3185 NULL, // #33 (QUAKE)
3186 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3187 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3188 VM_rint, // #36 float(float v) rint (QUAKE)
3189 VM_floor, // #37 float(float v) floor (QUAKE)
3190 VM_ceil, // #38 float(float v) ceil (QUAKE)
3191 NULL, // #39 (QUAKE)
3192 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3193 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3194 NULL, // #42 (QUAKE)
3195 VM_fabs, // #43 float(float f) fabs (QUAKE)
3196 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3197 VM_cvar, // #45 float(string s) cvar (QUAKE)
3198 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3199 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3200 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3201 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3202 NULL, // #50 (QUAKE)
3203 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3204 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3205 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3206 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3207 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3208 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3209 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3210 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3211 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3212 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3213 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3214 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3215 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3216 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3217 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3218 NULL, // #66 (QUAKE)
3219 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3220 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3221 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3222 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3223 NULL, // #71 (QUAKE)
3224 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3225 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3226 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3227 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3228 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3229 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3230 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3231 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3232 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3233 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3234 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3235 NULL, // #83 (QUAKE)
3236 NULL, // #84 (QUAKE)
3237 NULL, // #85 (QUAKE)
3238 NULL, // #86 (QUAKE)
3239 NULL, // #87 (QUAKE)
3240 NULL, // #88 (QUAKE)
3241 NULL, // #89 (QUAKE)
3242 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3243 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3244 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3245 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3246 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3247 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3248 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3249 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3250 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3251 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3252 // FrikaC and Telejano range #100-#199
3263 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3264 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3265 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3266 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3267 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3268 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3269 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3270 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3271 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3272 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3353 // FTEQW range #200-#299
3372 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3375 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3376 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3377 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3378 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3379 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3380 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3381 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3382 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3383 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3384 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3386 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3394 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3417 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.
3418 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
3419 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3420 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3421 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)
3422 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
3423 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)
3424 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)
3425 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)
3426 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)
3427 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)
3428 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
3429 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)
3430 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
3431 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.
3454 // CSQC range #300-#399
3455 NULL, // #300 void() clearscene (EXT_CSQC)
3456 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3457 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3458 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3459 NULL, // #304 void() renderscene (EXT_CSQC)
3460 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3461 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3462 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3463 NULL, // #308 void() R_EndPolygon
3465 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3466 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3470 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3471 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3472 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3473 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3474 NULL, // #319 void(string name) freepic (EXT_CSQC)
3475 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3476 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3477 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3478 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3479 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3480 NULL, // #325 void(void) drawresetcliparea
3485 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3486 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3487 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3488 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3489 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3490 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3491 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3492 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3493 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3494 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3495 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3496 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3497 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3498 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3499 NULL, // #344 vector() getmousepos (EXT_CSQC)
3500 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3501 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3502 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3503 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3504 NULL, // #349 float() isdemo (EXT_CSQC)
3505 VM_isserver, // #350 float() isserver (EXT_CSQC)
3506 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3507 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3508 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3509 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3515 NULL, // #360 float() readbyte (EXT_CSQC)
3516 NULL, // #361 float() readchar (EXT_CSQC)
3517 NULL, // #362 float() readshort (EXT_CSQC)
3518 NULL, // #363 float() readlong (EXT_CSQC)
3519 NULL, // #364 float() readcoord (EXT_CSQC)
3520 NULL, // #365 float() readangle (EXT_CSQC)
3521 NULL, // #366 string() readstring (EXT_CSQC)
3522 NULL, // #367 float() readfloat (EXT_CSQC)
3555 // LordHavoc's range #400-#499
3556 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3557 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3558 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3559 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3560 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3561 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3562 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3563 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3564 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)
3565 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3566 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3567 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3568 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3569 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3570 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3571 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3572 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3573 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3574 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3575 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3576 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3577 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3578 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3579 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3580 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3581 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3582 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3583 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3584 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3585 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3586 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3587 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3588 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3589 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3590 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3591 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3592 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3593 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3594 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3595 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3596 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3597 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3598 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3599 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3600 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3601 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3602 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3603 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3604 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3605 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3606 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3607 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3608 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3609 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3610 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3611 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3612 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3613 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3615 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3616 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3617 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3618 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3619 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3620 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3621 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3622 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3623 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3624 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3625 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3627 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3628 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3629 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3630 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3631 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3632 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3633 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3634 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3635 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3636 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3637 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3638 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3639 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3640 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3641 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3642 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3650 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3651 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3652 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3653 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3654 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3655 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3656 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3657 VM_SV_WritePicture, // #501
3659 VM_whichpack, // #503 string(string) whichpack = #503;
3666 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3667 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3668 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3669 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)
3670 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3671 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3672 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3673 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3674 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3675 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3685 VM_loadfromdata, // #529
3686 VM_loadfromfile, // #530
3687 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3689 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3690 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3696 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3697 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3698 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3761 VM_callfunction, // #605
3762 VM_writetofile, // #606
3763 VM_isfunction, // #607
3769 VM_parseentitydata, // #613
3780 VM_SV_getextresponse, // #624 string getextresponse(void)
3783 VM_sprintf, // #627 string sprintf(string format, ...)
3784 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3785 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3789 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3791 void VM_SV_Cmd_Init(void)
3796 void VM_SV_Cmd_Reset(void)
3798 World_End(&sv.world);
3799 if(PRVM_serverfunction(SV_Shutdown))
3801 func_t s = PRVM_serverfunction(SV_Shutdown);
3802 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3803 PRVM_ExecuteProgram(s,"SV_Shutdown() required");