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 "
57 "DP_GFX_EXTERNALTEXTURES "
58 "DP_GFX_EXTERNALTEXTURES_PERMAP "
60 "DP_GFX_MODEL_INTERPOLATION "
61 "DP_GFX_QUAKE3MODELTAGS "
65 "DP_GFX_FONTS_FREETYPE "
67 "DP_FONT_VARIABLEWIDTH "
69 "DP_HALFLIFE_MAP_CVAR "
72 "DP_LIGHTSTYLE_STATICVALUE "
76 "DP_MOVETYPEBOUNCEMISSILE "
77 "DP_MOVETYPEFLYWORLDONLY "
80 "DP_QC_ASINACOSATANATAN2TAN "
86 "DP_QC_CVAR_DEFSTRING "
87 "DP_QC_CVAR_DESCRIPTION "
91 "DP_QC_DIGEST_SHA256 "
96 "DP_QC_EXTRESPONSEPACKET "
98 "DP_QC_FINDCHAINFLAGS "
99 "DP_QC_FINDCHAINFLOAT "
100 "DP_QC_FINDCHAIN_TOFIELD "
106 "DP_QC_GETSURFACETRIANGLE "
107 "DP_QC_GETSURFACEPOINTATTRIBUTE "
109 "DP_QC_GETTAGINFO_BONEPROPERTIES "
111 "DP_QC_GETTIME_CDTRACK "
115 "DP_QC_MULTIPLETEMPSTRINGS "
116 "DP_QC_NUM_FOR_EDICT "
118 "DP_QC_SINCOSSQRTPOW "
121 "DP_QC_STRINGBUFFERS "
122 "DP_QC_STRINGBUFFERS_CVARLIST "
123 "DP_QC_STRINGCOLORFUNCTIONS "
124 "DP_QC_STRING_CASE_FUNCTIONS "
126 "DP_QC_TOKENIZEBYSEPARATOR "
127 "DP_QC_TOKENIZE_CONSOLE "
130 "DP_QC_TRACE_MOVETYPE_HITMODEL "
131 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
132 "DP_QC_UNLIMITEDTEMPSTRINGS "
136 "DP_QC_VECTOANGLES_WITH_ROLL "
137 "DP_QC_VECTORVECTORS "
144 "DP_SKELETONOBJECTS "
145 "DP_SND_DIRECTIONLESSATTNNONE "
147 "DP_SND_SOUND7_WIP1 "
148 "DP_SND_SOUND7_WIP2 "
152 "DP_SND_GETSOUNDTIME "
154 "DP_VIDEO_SUBTITLES "
158 "DP_SV_BOUNCEFACTOR "
159 "DP_SV_CLIENTCAMERA "
160 "DP_SV_CLIENTCOLORS "
163 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
164 "DP_SV_DISCARDABLEDEMO "
165 "DP_SV_DRAWONLYTOCLIENT "
168 "DP_SV_ENTITYCONTENTSTRANSITION "
169 "DP_SV_MODELFLAGS_AS_EFFECTS "
170 "DP_SV_MOVETYPESTEP_LANDEVENT "
172 "DP_SV_NODRAWTOCLIENT "
173 "DP_SV_ONENTITYNOSPAWNFUNCTION "
174 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
176 "DP_SV_PING_PACKETLOSS "
177 "DP_SV_PLAYERPHYSICS "
179 "DP_SV_POINTPARTICLES "
181 "DP_SV_PRECACHEANYTIME "
185 "DP_SV_ROTATINGBMODEL "
189 "DP_SV_SPAWNFUNC_PREFIX "
190 "DP_SV_WRITEPICTURE "
191 "DP_SV_WRITEUNTERMINATEDSTRING "
195 "DP_TE_EXPLOSIONRGB "
197 "DP_TE_PARTICLECUBE "
198 "DP_TE_PARTICLERAIN "
199 "DP_TE_PARTICLESNOW "
201 "DP_TE_QUADEFFECTS1 "
204 "DP_TE_STANDARDEFFECTBUILTINS "
205 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
209 "FTE_CSQC_SKELETONOBJECTS "
212 "KRIMZON_SV_PARSECLIENTCOMMAND "
215 "NEXUIZ_PLAYERMODEL "
217 "PRYDON_CLIENTCURSOR "
218 "TENEBRAE_GFX_DLIGHTS "
221 //"EXT_CSQC " // not ready yet
228 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.
230 setorigin (entity, origin)
233 static void VM_SV_setorigin (void)
238 VM_SAFEPARMCOUNT(2, VM_setorigin);
240 e = PRVM_G_EDICT(OFS_PARM0);
241 if (e == prog->edicts)
243 VM_Warning("setorigin: can not modify world entity\n");
246 if (e->priv.server->free)
248 VM_Warning("setorigin: can not modify free entity\n");
251 org = PRVM_G_VECTOR(OFS_PARM1);
252 VectorCopy (org, PRVM_serveredictvector(e, origin));
253 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
254 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
258 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
259 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
263 for (i=0 ; i<3 ; i++)
265 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
267 // set derived values
268 VectorCopy (min, PRVM_serveredictvector(e, mins));
269 VectorCopy (max, PRVM_serveredictvector(e, maxs));
270 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
279 the size box is rotated by the current angle
280 LordHavoc: no it isn't...
282 setsize (entity, minvector, maxvector)
285 static void VM_SV_setsize (void)
290 VM_SAFEPARMCOUNT(3, VM_setsize);
292 e = PRVM_G_EDICT(OFS_PARM0);
293 if (e == prog->edicts)
295 VM_Warning("setsize: can not modify world entity\n");
298 if (e->priv.server->free)
300 VM_Warning("setsize: can not modify free entity\n");
303 min = PRVM_G_VECTOR(OFS_PARM1);
304 max = PRVM_G_VECTOR(OFS_PARM2);
305 SetMinMaxSize (e, min, max, false);
313 setmodel(entity, model)
316 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
317 static void VM_SV_setmodel (void)
323 VM_SAFEPARMCOUNT(2, VM_setmodel);
325 e = PRVM_G_EDICT(OFS_PARM0);
326 if (e == prog->edicts)
328 VM_Warning("setmodel: can not modify world entity\n");
331 if (e->priv.server->free)
333 VM_Warning("setmodel: can not modify free entity\n");
336 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
337 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
338 PRVM_serveredictfloat(e, modelindex) = i;
340 mod = SV_GetModelByIndex(i);
344 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
345 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
347 SetMinMaxSize (e, quakemins, quakemaxs, true);
350 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
357 single print to a specific client
359 sprint(clientent, value)
362 static void VM_SV_sprint (void)
366 char string[VM_STRINGTEMP_LENGTH];
368 VM_VarString(1, string, sizeof(string));
370 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
372 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
373 // LordHavoc: div0 requested that sprintto world operate like print
380 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
382 VM_Warning("tried to centerprint to a non-client\n");
386 client = svs.clients + entnum-1;
387 if (!client->netconnection)
390 MSG_WriteChar(&client->netconnection->message,svc_print);
391 MSG_WriteString(&client->netconnection->message, string);
399 single print to a specific client
401 centerprint(clientent, value)
404 static void VM_SV_centerprint (void)
408 char string[VM_STRINGTEMP_LENGTH];
410 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
412 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
414 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
416 VM_Warning("tried to centerprint to a non-client\n");
420 client = svs.clients + entnum-1;
421 if (!client->netconnection)
424 VM_VarString(1, string, sizeof(string));
425 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
426 MSG_WriteString(&client->netconnection->message, string);
433 particle(origin, color, count)
436 static void VM_SV_particle (void)
442 VM_SAFEPARMCOUNT(4, VM_SV_particle);
444 org = PRVM_G_VECTOR(OFS_PARM0);
445 dir = PRVM_G_VECTOR(OFS_PARM1);
446 color = PRVM_G_FLOAT(OFS_PARM2);
447 count = PRVM_G_FLOAT(OFS_PARM3);
448 SV_StartParticle (org, dir, (int)color, (int)count);
458 static void VM_SV_ambientsound (void)
462 float vol, attenuation;
465 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
467 pos = PRVM_G_VECTOR (OFS_PARM0);
468 samp = PRVM_G_STRING(OFS_PARM1);
469 vol = PRVM_G_FLOAT(OFS_PARM2);
470 attenuation = PRVM_G_FLOAT(OFS_PARM3);
472 // check to see if samp was properly precached
473 soundnum = SV_SoundIndex(samp, 1);
481 // add an svc_spawnambient command to the level signon packet
484 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
486 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
488 MSG_WriteVector(&sv.signon, pos, sv.protocol);
490 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
491 MSG_WriteShort (&sv.signon, soundnum);
493 MSG_WriteByte (&sv.signon, soundnum);
495 MSG_WriteByte (&sv.signon, (int)(vol*255));
496 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
504 Each entity can have eight independant sound sources, like voice,
507 Channel 0 is an auto-allocate channel, the others override anything
508 already running on that entity/channel pair.
510 An attenuation of 0 will play full volume everywhere in the level.
511 Larger attenuations will drop off.
515 static void VM_SV_sound (void)
519 prvm_edict_t *entity;
525 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
527 entity = PRVM_G_EDICT(OFS_PARM0);
528 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
529 sample = PRVM_G_STRING(OFS_PARM2);
530 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
533 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
537 attenuation = PRVM_G_FLOAT(OFS_PARM4);
541 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
546 if(channel >= 8 && channel <= 15) // weird QW feature
548 flags |= CHANFLAG_RELIABLE;
553 flags = PRVM_G_FLOAT(OFS_PARM6);
555 if (volume < 0 || volume > 255)
557 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
561 if (attenuation < 0 || attenuation > 4)
563 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
567 channel = CHAN_USER2ENGINE(channel);
569 if (!IS_CHAN(channel))
571 VM_Warning("SV_StartSound: channel must be in range 0-127\n");
575 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE, pitchchange);
582 Follows the same logic as VM_SV_sound, except instead of
583 an entity, an origin for the sound is provided, and channel
584 is omitted (since no entity is being tracked).
588 static void VM_SV_pointsound(void)
596 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
598 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
599 sample = PRVM_G_STRING(OFS_PARM1);
600 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
601 attenuation = PRVM_G_FLOAT(OFS_PARM3);
602 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
604 if (volume < 0 || volume > 255)
606 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
610 if (attenuation < 0 || attenuation > 4)
612 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
616 SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
623 Used for use tracing and shot targeting
624 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
625 if the tryents flag is set.
627 traceline (vector1, vector2, movetype, ignore)
630 static void VM_SV_traceline (void)
637 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
639 prog->xfunction->builtinsprofile += 30;
641 v1 = PRVM_G_VECTOR(OFS_PARM0);
642 v2 = PRVM_G_VECTOR(OFS_PARM1);
643 move = (int)PRVM_G_FLOAT(OFS_PARM2);
644 ent = PRVM_G_EDICT(OFS_PARM3);
646 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]))
647 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));
649 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
651 VM_SetTraceGlobals(&trace);
659 Used for use tracing and shot targeting
660 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
661 if the tryents flag is set.
663 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
666 // LordHavoc: added this for my own use, VERY useful, similar to traceline
667 static void VM_SV_tracebox (void)
669 float *v1, *v2, *m1, *m2;
674 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
676 prog->xfunction->builtinsprofile += 30;
678 v1 = PRVM_G_VECTOR(OFS_PARM0);
679 m1 = PRVM_G_VECTOR(OFS_PARM1);
680 m2 = PRVM_G_VECTOR(OFS_PARM2);
681 v2 = PRVM_G_VECTOR(OFS_PARM3);
682 move = (int)PRVM_G_FLOAT(OFS_PARM4);
683 ent = PRVM_G_EDICT(OFS_PARM5);
685 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]))
686 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));
688 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
690 VM_SetTraceGlobals(&trace);
693 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
698 vec3_t original_origin;
699 vec3_t original_velocity;
700 vec3_t original_angles;
701 vec3_t original_avelocity;
704 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
705 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
706 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
707 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
709 gravity = PRVM_serveredictfloat(tossent, gravity);
712 gravity *= sv_gravity.value * 0.025;
714 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
716 SV_CheckVelocity (tossent);
717 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
718 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
719 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
720 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
721 trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
722 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
723 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
725 if (trace.fraction < 1)
729 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
730 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
731 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
732 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
737 static void VM_SV_tracetoss (void)
741 prvm_edict_t *ignore;
743 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
745 prog->xfunction->builtinsprofile += 600;
747 ent = PRVM_G_EDICT(OFS_PARM0);
748 if (ent == prog->edicts)
750 VM_Warning("tracetoss: can not use world entity\n");
753 ignore = PRVM_G_EDICT(OFS_PARM1);
755 trace = SV_Trace_Toss (ent, ignore);
757 VM_SetTraceGlobals(&trace);
760 //============================================================================
762 static int checkpvsbytes;
763 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
765 static int VM_SV_newcheckclient (int check)
771 // cycle to the next one
773 check = bound(1, check, svs.maxclients);
774 if (check == svs.maxclients)
782 prog->xfunction->builtinsprofile++;
784 if (i == svs.maxclients+1)
786 // look up the client's edict
787 ent = PRVM_EDICT_NUM(i);
788 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
789 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
791 // found a valid client (possibly the same one again)
795 // get the PVS for the entity
796 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
798 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
799 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
808 Returns a client (or object that has a client enemy) that would be a
811 If there is more than one valid option, they are cycled each frame
813 If (self.origin + self.viewofs) is not in the PVS of the current target,
814 it is not returned at all.
819 int c_invis, c_notvis;
820 static void VM_SV_checkclient (void)
822 prvm_edict_t *ent, *self;
825 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
827 // find a new check if on a new frame
828 if (sv.time - sv.lastchecktime >= 0.1)
830 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
831 sv.lastchecktime = sv.time;
834 // return check if it might be visible
835 ent = PRVM_EDICT_NUM(sv.lastcheck);
836 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
838 VM_RETURN_EDICT(prog->edicts);
842 // if current entity can't possibly see the check entity, return 0
843 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
844 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
845 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
848 VM_RETURN_EDICT(prog->edicts);
852 // might be able to see it
854 VM_RETURN_EDICT(ent);
857 //============================================================================
863 Checks if an entity is in a point's PVS.
864 Should be fast but can be inexact.
866 float checkpvs(vector viewpos, entity viewee) = #240;
869 static void VM_SV_checkpvs (void)
872 prvm_edict_t *viewee;
877 unsigned char fatpvs[MAX_MAP_LEAFS/8];
880 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
881 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
882 viewee = PRVM_G_EDICT(OFS_PARM1);
884 if(viewee->priv.server->free)
886 VM_Warning("checkpvs: can not check free entity\n");
887 PRVM_G_FLOAT(OFS_RETURN) = 4;
892 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
894 // no PVS support on this worldmodel... darn
895 PRVM_G_FLOAT(OFS_RETURN) = 3;
898 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
901 // viewpos isn't in any PVS... darn
902 PRVM_G_FLOAT(OFS_RETURN) = 2;
905 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
907 // using fat PVS like FTEQW does (slow)
908 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
910 // no PVS support on this worldmodel... darn
911 PRVM_G_FLOAT(OFS_RETURN) = 3;
914 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
917 // viewpos isn't in any PVS... darn
918 PRVM_G_FLOAT(OFS_RETURN) = 2;
921 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
930 Sends text over to the client's execution buffer
932 stuffcmd (clientent, value, ...)
935 static void VM_SV_stuffcmd (void)
939 char string[VM_STRINGTEMP_LENGTH];
941 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
943 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
944 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
946 VM_Warning("Can't stuffcmd to a non-client\n");
950 VM_VarString(1, string, sizeof(string));
953 host_client = svs.clients + entnum-1;
954 Host_ClientCommands ("%s", string);
962 Returns a chain of entities that have origins within a spherical area
964 findradius (origin, radius)
967 static void VM_SV_findradius (void)
969 prvm_edict_t *ent, *chain;
970 vec_t radius, radius2;
971 vec3_t org, eorg, mins, maxs;
974 static prvm_edict_t *touchedicts[MAX_EDICTS];
977 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
980 chainfield = PRVM_G_INT(OFS_PARM2);
982 chainfield = prog->fieldoffsets.chain;
984 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
986 chain = (prvm_edict_t *)prog->edicts;
988 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
989 radius = PRVM_G_FLOAT(OFS_PARM1);
990 radius2 = radius * radius;
992 mins[0] = org[0] - (radius + 1);
993 mins[1] = org[1] - (radius + 1);
994 mins[2] = org[2] - (radius + 1);
995 maxs[0] = org[0] + (radius + 1);
996 maxs[1] = org[1] + (radius + 1);
997 maxs[2] = org[2] + (radius + 1);
998 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
999 if (numtouchedicts > MAX_EDICTS)
1001 // this never happens
1002 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1003 numtouchedicts = MAX_EDICTS;
1005 for (i = 0;i < numtouchedicts;i++)
1007 ent = touchedicts[i];
1008 prog->xfunction->builtinsprofile++;
1009 // Quake did not return non-solid entities but darkplaces does
1010 // (note: this is the reason you can't blow up fallen zombies)
1011 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1013 // LordHavoc: compare against bounding box rather than center so it
1014 // doesn't miss large objects, and use DotProduct instead of Length
1015 // for a major speedup
1016 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1017 if (sv_gameplayfix_findradiusdistancetobox.integer)
1019 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1020 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1021 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1024 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1025 if (DotProduct(eorg, eorg) < radius2)
1027 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1032 VM_RETURN_EDICT(chain);
1035 static void VM_SV_precache_sound (void)
1037 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1038 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1041 static void VM_SV_precache_model (void)
1043 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1044 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1045 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1052 float(float yaw, float dist[, settrace]) walkmove
1055 static void VM_SV_walkmove (void)
1064 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1066 // assume failure if it returns early
1067 PRVM_G_FLOAT(OFS_RETURN) = 0;
1069 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1070 if (ent == prog->edicts)
1072 VM_Warning("walkmove: can not modify world entity\n");
1075 if (ent->priv.server->free)
1077 VM_Warning("walkmove: can not modify free entity\n");
1080 yaw = PRVM_G_FLOAT(OFS_PARM0);
1081 dist = PRVM_G_FLOAT(OFS_PARM1);
1082 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1084 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1087 yaw = yaw*M_PI*2 / 360;
1089 move[0] = cos(yaw)*dist;
1090 move[1] = sin(yaw)*dist;
1093 // save program state, because SV_movestep may call other progs
1094 oldf = prog->xfunction;
1095 oldself = PRVM_serverglobaledict(self);
1097 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1100 // restore program state
1101 prog->xfunction = oldf;
1102 PRVM_serverglobaledict(self) = oldself;
1113 static void VM_SV_droptofloor (void)
1119 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1121 // assume failure if it returns early
1122 PRVM_G_FLOAT(OFS_RETURN) = 0;
1124 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1125 if (ent == prog->edicts)
1127 VM_Warning("droptofloor: can not modify world entity\n");
1130 if (ent->priv.server->free)
1132 VM_Warning("droptofloor: can not modify free entity\n");
1136 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1139 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1140 if (sv_gameplayfix_unstickentities.integer)
1141 SV_UnstickEntity(ent);
1143 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1144 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1147 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]);
1148 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1149 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1150 VectorSubtract(trace.endpos, offset, trace.endpos);
1151 if (trace.startsolid)
1153 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]);
1154 if (sv_gameplayfix_unstickentities.integer)
1155 SV_UnstickEntity(ent);
1157 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1158 PRVM_serveredictedict(ent, groundentity) = 0;
1159 PRVM_G_FLOAT(OFS_RETURN) = 1;
1161 else if (trace.fraction < 1)
1163 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]);
1164 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1165 if (sv_gameplayfix_unstickentities.integer)
1166 SV_UnstickEntity(ent);
1168 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1169 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1170 PRVM_G_FLOAT(OFS_RETURN) = 1;
1171 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1172 ent->priv.server->suspendedinairflag = true;
1177 if (trace.fraction != 1)
1179 if (trace.fraction < 1)
1180 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1182 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1183 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1184 PRVM_G_FLOAT(OFS_RETURN) = 1;
1185 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1186 ent->priv.server->suspendedinairflag = true;
1195 void(float style, string value) lightstyle
1198 static void VM_SV_lightstyle (void)
1205 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1207 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1208 val = PRVM_G_STRING(OFS_PARM1);
1210 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1211 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1214 // change the string in sv
1215 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1217 // send message to all clients on this server
1218 if (sv.state != ss_active)
1221 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1223 if (client->active && client->netconnection)
1225 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1226 MSG_WriteChar (&client->netconnection->message,style);
1227 MSG_WriteString (&client->netconnection->message, val);
1237 static void VM_SV_checkbottom (void)
1239 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1240 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1248 static void VM_SV_pointcontents (void)
1250 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1251 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1258 Pick a vector for the player to shoot along
1259 vector aim(entity, missilespeed)
1262 static void VM_SV_aim (void)
1264 prvm_edict_t *ent, *check, *bestent;
1265 vec3_t start, dir, end, bestdir;
1268 float dist, bestdist;
1271 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1273 // assume failure if it returns early
1274 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1275 // if sv_aim is so high it can't possibly accept anything, skip out early
1276 if (sv_aim.value >= 1)
1279 ent = PRVM_G_EDICT(OFS_PARM0);
1280 if (ent == prog->edicts)
1282 VM_Warning("aim: can not use world entity\n");
1285 if (ent->priv.server->free)
1287 VM_Warning("aim: can not use free entity\n");
1290 //speed = PRVM_G_FLOAT(OFS_PARM1);
1292 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1295 // try sending a trace straight
1296 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1297 VectorMA (start, 2048, dir, end);
1298 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1299 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1300 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1302 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1307 // try all possible entities
1308 VectorCopy (dir, bestdir);
1309 bestdist = sv_aim.value;
1312 check = PRVM_NEXT_EDICT(prog->edicts);
1313 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1315 prog->xfunction->builtinsprofile++;
1316 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1320 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1321 continue; // don't aim at teammate
1322 for (j=0 ; j<3 ; j++)
1323 end[j] = PRVM_serveredictvector(check, origin)[j]
1324 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1325 VectorSubtract (end, start, dir);
1326 VectorNormalize (dir);
1327 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1328 if (dist < bestdist)
1329 continue; // to far to turn
1330 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1331 if (tr.ent == check)
1332 { // can shoot at this one
1340 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1341 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1342 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1344 VectorNormalize (end);
1345 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1349 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1354 ===============================================================================
1358 ===============================================================================
1361 #define MSG_BROADCAST 0 // unreliable to all
1362 #define MSG_ONE 1 // reliable to one (msg_entity)
1363 #define MSG_ALL 2 // reliable to all
1364 #define MSG_INIT 3 // write to the init string
1365 #define MSG_ENTITY 5
1367 sizebuf_t *WriteDest (void)
1373 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1377 return &sv.datagram;
1380 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1381 entnum = PRVM_NUM_FOR_EDICT(ent);
1382 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1384 VM_Warning ("WriteDest: tried to write to non-client\n");
1385 return &sv.reliable_datagram;
1388 return &svs.clients[entnum-1].netconnection->message;
1391 VM_Warning ("WriteDest: bad destination\n");
1393 return &sv.reliable_datagram;
1399 return sv.writeentitiestoclient_msg;
1405 static void VM_SV_WriteByte (void)
1407 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1408 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1411 static void VM_SV_WriteChar (void)
1413 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1414 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1417 static void VM_SV_WriteShort (void)
1419 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1420 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1423 static void VM_SV_WriteLong (void)
1425 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1426 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1429 static void VM_SV_WriteAngle (void)
1431 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1432 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1435 static void VM_SV_WriteCoord (void)
1437 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1438 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1441 static void VM_SV_WriteString (void)
1443 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1444 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1447 static void VM_SV_WriteUnterminatedString (void)
1449 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1450 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1454 static void VM_SV_WriteEntity (void)
1456 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1457 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1460 // writes a picture as at most size bytes of data
1462 // IMGNAME \0 SIZE(short) IMGDATA
1463 // if failed to read/compress:
1465 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1466 static void VM_SV_WritePicture (void)
1468 const char *imgname;
1472 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1474 imgname = PRVM_G_STRING(OFS_PARM1);
1475 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1479 MSG_WriteString(WriteDest(), imgname);
1480 if(Image_Compress(imgname, size, &buf, &size))
1483 MSG_WriteShort(WriteDest(), size);
1484 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1489 MSG_WriteShort(WriteDest(), 0);
1493 //////////////////////////////////////////////////////////
1495 static void VM_SV_makestatic (void)
1500 // allow 0 parameters due to an id1 qc bug in which this function is used
1501 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1502 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1504 if (prog->argc >= 1)
1505 ent = PRVM_G_EDICT(OFS_PARM0);
1507 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1508 if (ent == prog->edicts)
1510 VM_Warning("makestatic: can not modify world entity\n");
1513 if (ent->priv.server->free)
1515 VM_Warning("makestatic: can not modify free entity\n");
1520 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1525 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1526 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1527 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1529 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1531 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1532 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1533 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1537 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1538 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1539 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1542 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1543 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1544 for (i=0 ; i<3 ; i++)
1546 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1547 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1550 // throw the entity away now
1554 //=============================================================================
1561 static void VM_SV_setspawnparms (void)
1567 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1569 ent = PRVM_G_EDICT(OFS_PARM0);
1570 i = PRVM_NUM_FOR_EDICT(ent);
1571 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1573 Con_Print("tried to setspawnparms on a non-client\n");
1577 // copy spawn parms out of the client_t
1578 client = svs.clients + i-1;
1579 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1580 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1587 Returns a color vector indicating the lighting at the requested point.
1589 (Internal Operation note: actually measures the light beneath the point, just like
1590 the model lighting on the client)
1595 static void VM_SV_getlight (void)
1597 vec3_t ambientcolor, diffusecolor, diffusenormal;
1599 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1600 p = PRVM_G_VECTOR(OFS_PARM0);
1601 VectorClear(ambientcolor);
1602 VectorClear(diffusecolor);
1603 VectorClear(diffusenormal);
1604 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1605 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1606 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1611 unsigned char type; // 1/2/8 or other value if isn't used
1615 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1616 static int vm_customstats_last;
1618 void VM_CustomStats_Clear (void)
1622 Z_Free(vm_customstats);
1623 vm_customstats = NULL;
1624 vm_customstats_last = -1;
1628 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1636 for(i=0; i<vm_customstats_last+1 ;i++)
1638 if(!vm_customstats[i].type)
1640 switch(vm_customstats[i].type)
1642 //string as 16 bytes
1645 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1646 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1647 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1648 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1649 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1651 //float field sent as-is
1653 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1655 //integer value of float field
1657 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1665 // void(float index, float type, .void field) SV_AddStat = #232;
1666 // Set up an auto-sent player stat.
1667 // Client's get thier own fields sent to them. Index may not be less than 32.
1668 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1669 // 1: string (4 stats carrying a total of 16 charactures)
1670 // 2: float (one stat, float converted to an integer for transportation)
1671 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1672 static void VM_SV_AddStat (void)
1677 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1681 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1684 VM_Warning("PF_SV_AddStat: not enough memory\n");
1688 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1689 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1690 off = PRVM_G_INT (OFS_PARM2);
1695 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1698 if(i >= (MAX_CL_STATS-32))
1700 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1703 if(i > (MAX_CL_STATS-32-4) && type == 1)
1705 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1708 vm_customstats[i].type = type;
1709 vm_customstats[i].fieldoffset = off;
1710 if(vm_customstats_last < i)
1711 vm_customstats_last = i;
1718 copies data from one entity to another
1720 copyentity(src, dst)
1723 static void VM_SV_copyentity (void)
1725 prvm_edict_t *in, *out;
1726 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1727 in = PRVM_G_EDICT(OFS_PARM0);
1728 if (in == prog->edicts)
1730 VM_Warning("copyentity: can not read world entity\n");
1733 if (in->priv.server->free)
1735 VM_Warning("copyentity: can not read free entity\n");
1738 out = PRVM_G_EDICT(OFS_PARM1);
1739 if (out == prog->edicts)
1741 VM_Warning("copyentity: can not modify world entity\n");
1744 if (out->priv.server->free)
1746 VM_Warning("copyentity: can not modify free entity\n");
1749 memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
1758 sets the color of a client and broadcasts the update to all connected clients
1760 setcolor(clientent, value)
1763 static void VM_SV_setcolor (void)
1768 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1769 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1770 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1772 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1774 Con_Print("tried to setcolor a non-client\n");
1778 client = svs.clients + entnum-1;
1781 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1782 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1785 if (client->old_colors != client->colors)
1787 client->old_colors = client->colors;
1788 // send notification to all clients
1789 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1790 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1791 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1799 effect(origin, modelname, startframe, framecount, framerate)
1802 static void VM_SV_effect (void)
1806 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1807 s = PRVM_G_STRING(OFS_PARM1);
1810 VM_Warning("effect: no model specified\n");
1814 i = SV_ModelIndex(s, 1);
1817 VM_Warning("effect: model not precached\n");
1821 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1823 VM_Warning("effect: framecount < 1\n");
1827 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1829 VM_Warning("effect: framerate < 1\n");
1833 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));
1836 static void VM_SV_te_blood (void)
1838 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1839 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1841 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1842 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1844 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1845 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1848 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1849 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1850 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1852 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1853 SV_FlushBroadcastMessages();
1856 static void VM_SV_te_bloodshower (void)
1858 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1859 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1861 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1862 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1864 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1865 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1866 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1868 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1869 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1870 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1874 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1875 SV_FlushBroadcastMessages();
1878 static void VM_SV_te_explosionrgb (void)
1880 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1881 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1882 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1884 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1885 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1886 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1888 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1889 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1890 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1891 SV_FlushBroadcastMessages();
1894 static void VM_SV_te_particlecube (void)
1896 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1897 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1899 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1900 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1911 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1912 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1914 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1916 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1917 // gravity true/false
1918 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1920 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1921 SV_FlushBroadcastMessages();
1924 static void VM_SV_te_particlerain (void)
1926 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1927 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1929 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1930 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1934 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1936 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1941 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1942 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1944 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1946 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1947 SV_FlushBroadcastMessages();
1950 static void VM_SV_te_particlesnow (void)
1952 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1953 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1955 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1956 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1964 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1970 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1972 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1973 SV_FlushBroadcastMessages();
1976 static void VM_SV_te_spark (void)
1978 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1979 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1981 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1982 MSG_WriteByte(&sv.datagram, TE_SPARK);
1984 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1985 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1988 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1989 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1990 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1992 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1993 SV_FlushBroadcastMessages();
1996 static void VM_SV_te_gunshotquad (void)
1998 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1999 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2000 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2002 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2004 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2005 SV_FlushBroadcastMessages();
2008 static void VM_SV_te_spikequad (void)
2010 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2011 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2012 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2014 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2015 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2016 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2017 SV_FlushBroadcastMessages();
2020 static void VM_SV_te_superspikequad (void)
2022 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2023 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2024 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2026 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2028 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2029 SV_FlushBroadcastMessages();
2032 static void VM_SV_te_explosionquad (void)
2034 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2035 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2036 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2038 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2039 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2040 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2041 SV_FlushBroadcastMessages();
2044 static void VM_SV_te_smallflash (void)
2046 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2047 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2048 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2050 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2052 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2053 SV_FlushBroadcastMessages();
2056 static void VM_SV_te_customflash (void)
2058 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2059 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2061 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2062 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2064 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2065 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2066 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2068 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2070 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2072 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2073 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2074 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2075 SV_FlushBroadcastMessages();
2078 static void VM_SV_te_gunshot (void)
2080 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2081 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2082 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2084 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2085 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2086 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2087 SV_FlushBroadcastMessages();
2090 static void VM_SV_te_spike (void)
2092 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2093 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2094 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2096 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2097 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2098 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2099 SV_FlushBroadcastMessages();
2102 static void VM_SV_te_superspike (void)
2104 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2105 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2106 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2108 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2109 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2110 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2111 SV_FlushBroadcastMessages();
2114 static void VM_SV_te_explosion (void)
2116 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2117 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2118 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2120 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2121 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2122 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2123 SV_FlushBroadcastMessages();
2126 static void VM_SV_te_tarexplosion (void)
2128 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2129 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2130 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2132 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2133 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2134 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2135 SV_FlushBroadcastMessages();
2138 static void VM_SV_te_wizspike (void)
2140 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2141 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2142 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2144 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2145 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2146 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2147 SV_FlushBroadcastMessages();
2150 static void VM_SV_te_knightspike (void)
2152 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2153 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2154 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2156 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2157 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2158 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2159 SV_FlushBroadcastMessages();
2162 static void VM_SV_te_lavasplash (void)
2164 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2165 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2166 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2168 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2169 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2170 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2171 SV_FlushBroadcastMessages();
2174 static void VM_SV_te_teleport (void)
2176 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2177 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2178 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2180 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2181 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2182 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2183 SV_FlushBroadcastMessages();
2186 static void VM_SV_te_explosion2 (void)
2188 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2189 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2190 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2192 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2193 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2194 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2196 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2197 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2198 SV_FlushBroadcastMessages();
2201 static void VM_SV_te_lightning1 (void)
2203 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2204 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2205 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2207 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2209 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2210 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2211 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2213 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2214 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2215 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2216 SV_FlushBroadcastMessages();
2219 static void VM_SV_te_lightning2 (void)
2221 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2222 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2223 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2225 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2227 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2231 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2232 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2234 SV_FlushBroadcastMessages();
2237 static void VM_SV_te_lightning3 (void)
2239 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2240 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2241 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2243 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2245 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2246 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2247 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2249 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2250 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2251 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2252 SV_FlushBroadcastMessages();
2255 static void VM_SV_te_beam (void)
2257 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2258 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2259 MSG_WriteByte(&sv.datagram, TE_BEAM);
2261 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2263 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2264 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2265 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2267 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2268 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2269 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2270 SV_FlushBroadcastMessages();
2273 static void VM_SV_te_plasmaburn (void)
2275 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2276 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2277 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2278 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2279 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2280 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2281 SV_FlushBroadcastMessages();
2284 static void VM_SV_te_flamejet (void)
2286 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2287 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2288 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2290 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2291 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2292 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2294 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2295 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2296 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2298 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2299 SV_FlushBroadcastMessages();
2302 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2303 //this function originally written by KrimZon, made shorter by LordHavoc
2304 static void VM_SV_clientcommand (void)
2306 client_t *temp_client;
2308 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2310 //find client for this entity
2311 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2312 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2314 Con_Print("PF_clientcommand: entity is not a client\n");
2318 temp_client = host_client;
2319 host_client = svs.clients + i;
2320 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2321 host_client = temp_client;
2324 //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)
2325 static void VM_SV_setattachment (void)
2327 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2328 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2329 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2332 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2334 if (e == prog->edicts)
2336 VM_Warning("setattachment: can not modify world entity\n");
2339 if (e->priv.server->free)
2341 VM_Warning("setattachment: can not modify free entity\n");
2345 if (tagentity == NULL)
2346 tagentity = prog->edicts;
2350 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2352 model = SV_GetModelFromEdict(tagentity);
2355 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2357 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);
2360 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));
2363 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2364 PRVM_serveredictfloat(e, tag_index) = tagindex;
2367 /////////////////////////////////////////
2368 // DP_MD3_TAGINFO extension coded by VorteX
2370 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2374 i = (int)PRVM_serveredictfloat(e, modelindex);
2375 if (i < 1 || i >= MAX_MODELS)
2378 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2381 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2388 Matrix4x4_CreateIdentity(tag_localmatrix);
2390 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2392 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2403 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2406 float pitchsign = 1;
2408 scale = PRVM_serveredictfloat(ent, scale);
2413 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);
2416 pitchsign = SV_GetPitchSign(ent);
2417 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);
2421 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2424 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2426 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2427 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2428 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2429 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2431 *out = identitymatrix;
2435 // Warnings/errors code:
2436 // 0 - normal (everything all-right)
2439 // 3 - null or non-precached model
2440 // 4 - no tags with requested index
2441 // 5 - runaway loop at attachment chain
2442 extern cvar_t cl_bob;
2443 extern cvar_t cl_bobcycle;
2444 extern cvar_t cl_bobup;
2445 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2448 int modelindex, attachloop;
2449 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2452 *out = identitymatrix; // warnings and errors return identical matrix
2454 if (ent == prog->edicts)
2456 if (ent->priv.server->free)
2459 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2460 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2463 model = SV_GetModelByIndex(modelindex);
2465 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2466 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2467 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2469 tagmatrix = identitymatrix;
2470 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2474 if (attachloop >= 256) // prevent runaway looping
2476 // apply transformation by child's tagindex on parent entity and then
2477 // by parent entity itself
2478 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2479 if (ret && attachloop == 0)
2481 SV_GetEntityMatrix(ent, &entitymatrix, false);
2482 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2483 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2484 // next iteration we process the parent entity
2485 if (PRVM_serveredictedict(ent, tag_entity))
2487 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2488 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2495 // RENDER_VIEWMODEL magic
2496 if (PRVM_serveredictedict(ent, viewmodelforclient))
2498 Matrix4x4_Copy(&tagmatrix, out);
2499 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2501 SV_GetEntityMatrix(ent, &entitymatrix, true);
2502 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2505 // Cl_bob, ported from rendering code
2506 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2509 // LordHavoc: this code is *weird*, but not replacable (I think it
2510 // should be done in QC on the server, but oh well, quake is quake)
2511 // LordHavoc: figured out bobup: the time at which the sin is at 180
2512 // degrees (which allows lengthening or squishing the peak or valley)
2513 cycle = sv.time/cl_bobcycle.value;
2514 cycle -= (int)cycle;
2515 if (cycle < cl_bobup.value)
2516 cycle = sin(M_PI * cycle / cl_bobup.value);
2518 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2519 // bob is proportional to velocity in the xy plane
2520 // (don't count Z, or jumping messes it up)
2521 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;
2522 bob = bob*0.3 + bob*0.7*cycle;
2523 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2530 //float(entity ent, string tagname) gettagindex;
2532 static void VM_SV_gettagindex (void)
2535 const char *tag_name;
2538 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2540 ent = PRVM_G_EDICT(OFS_PARM0);
2541 tag_name = PRVM_G_STRING(OFS_PARM1);
2543 if (ent == prog->edicts)
2545 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2548 if (ent->priv.server->free)
2550 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2555 if (!SV_GetModelFromEdict(ent))
2556 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2559 tag_index = SV_GetTagIndex(ent, tag_name);
2561 if(developer_extra.integer)
2562 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2564 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2567 //vector(entity ent, float tagindex) gettaginfo;
2568 static void VM_SV_gettaginfo (void)
2572 matrix4x4_t tag_matrix;
2573 matrix4x4_t tag_localmatrix;
2575 const char *tagname;
2577 vec3_t fo, le, up, trans;
2578 const dp_model_t *model;
2580 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2582 e = PRVM_G_EDICT(OFS_PARM0);
2583 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2585 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2586 Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
2587 VectorScale(le, -1, PRVM_serverglobalvector(v_right));
2588 model = SV_GetModelFromEdict(e);
2589 VM_GenerateFrameGroupBlend(e->priv.server->framegroupblend, e);
2590 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
2591 VM_UpdateEdictSkeleton(e, model, e->priv.server->frameblend);
2592 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2593 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2595 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2596 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(tagname) : 0;
2597 VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
2598 VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
2599 VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
2600 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2605 VM_Warning("gettagindex: can't affect world entity\n");
2608 VM_Warning("gettagindex: can't affect free entity\n");
2611 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2614 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2617 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2622 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2623 static void VM_SV_dropclient (void)
2626 client_t *oldhostclient;
2627 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2628 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2629 if (clientnum < 0 || clientnum >= svs.maxclients)
2631 VM_Warning("dropclient: not a client\n");
2634 if (!svs.clients[clientnum].active)
2636 VM_Warning("dropclient: that client slot is not connected\n");
2639 oldhostclient = host_client;
2640 host_client = svs.clients + clientnum;
2641 SV_DropClient(false);
2642 host_client = oldhostclient;
2645 //entity() spawnclient (DP_SV_BOTCLIENT)
2646 static void VM_SV_spawnclient (void)
2650 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2651 prog->xfunction->builtinsprofile += 2;
2653 for (i = 0;i < svs.maxclients;i++)
2655 if (!svs.clients[i].active)
2657 prog->xfunction->builtinsprofile += 100;
2658 SV_ConnectClient (i, NULL);
2659 // this has to be set or else ClientDisconnect won't be called
2660 // we assume the qc will call ClientConnect...
2661 svs.clients[i].clientconnectcalled = true;
2662 ed = PRVM_EDICT_NUM(i + 1);
2666 VM_RETURN_EDICT(ed);
2669 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2670 static void VM_SV_clienttype (void)
2673 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2674 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2675 if (clientnum < 0 || clientnum >= svs.maxclients)
2676 PRVM_G_FLOAT(OFS_RETURN) = 3;
2677 else if (!svs.clients[clientnum].active)
2678 PRVM_G_FLOAT(OFS_RETURN) = 0;
2679 else if (svs.clients[clientnum].netconnection)
2680 PRVM_G_FLOAT(OFS_RETURN) = 1;
2682 PRVM_G_FLOAT(OFS_RETURN) = 2;
2689 string(string key) serverkey
2692 void VM_SV_serverkey(void)
2694 char string[VM_STRINGTEMP_LENGTH];
2695 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2696 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2697 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2700 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2701 static void VM_SV_setmodelindex (void)
2706 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2708 e = PRVM_G_EDICT(OFS_PARM0);
2709 if (e == prog->edicts)
2711 VM_Warning("setmodelindex: can not modify world entity\n");
2714 if (e->priv.server->free)
2716 VM_Warning("setmodelindex: can not modify free entity\n");
2719 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2720 if (i <= 0 || i >= MAX_MODELS)
2722 VM_Warning("setmodelindex: invalid modelindex\n");
2725 if (!sv.model_precache[i][0])
2727 VM_Warning("setmodelindex: model not precached\n");
2731 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
2732 PRVM_serveredictfloat(e, modelindex) = i;
2734 mod = SV_GetModelByIndex(i);
2738 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2739 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2741 SetMinMaxSize (e, quakemins, quakemaxs, true);
2744 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2747 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2748 static void VM_SV_modelnameforindex (void)
2751 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2753 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2755 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2756 if (i <= 0 || i >= MAX_MODELS)
2758 VM_Warning("modelnameforindex: invalid modelindex\n");
2761 if (!sv.model_precache[i][0])
2763 VM_Warning("modelnameforindex: model not precached\n");
2767 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2770 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2771 static void VM_SV_particleeffectnum (void)
2774 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2775 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2778 PRVM_G_FLOAT(OFS_RETURN) = i;
2781 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2782 static void VM_SV_trailparticles (void)
2784 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2786 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2789 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2790 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2791 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2792 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2793 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2794 SV_FlushBroadcastMessages();
2797 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2798 static void VM_SV_pointparticles (void)
2800 int effectnum, count;
2802 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2804 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2807 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2808 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2809 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2810 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2811 if (count == 1 && !VectorLength2(vel))
2814 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2815 MSG_WriteShort(&sv.datagram, effectnum);
2816 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2820 // 1+2+12+12+2=29 bytes
2821 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2822 MSG_WriteShort(&sv.datagram, effectnum);
2823 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2824 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2825 MSG_WriteShort(&sv.datagram, count);
2828 SV_FlushBroadcastMessages();
2831 //PF_setpause, // void(float pause) setpause = #531;
2832 static void VM_SV_setpause(void) {
2834 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2835 if (pauseValue != 0) { //pause the game
2837 sv.pausedstart = Sys_DoubleTime();
2838 } else { //disable pause, in case it was enabled
2839 if (sv.paused != 0) {
2844 // send notification to all clients
2845 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2846 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2849 // #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.
2850 static void VM_SV_skel_create(void)
2852 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2853 dp_model_t *model = SV_GetModelByIndex(modelindex);
2854 skeleton_t *skeleton;
2856 PRVM_G_FLOAT(OFS_RETURN) = 0;
2857 if (!model || !model->num_bones)
2859 for (i = 0;i < MAX_EDICTS;i++)
2860 if (!prog->skeletons[i])
2862 if (i == MAX_EDICTS)
2864 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2865 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2866 skeleton->model = model;
2867 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2868 // initialize to identity matrices
2869 for (i = 0;i < skeleton->model->num_bones;i++)
2870 skeleton->relativetransforms[i] = identitymatrix;
2873 // #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
2874 static void VM_SV_skel_build(void)
2876 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2877 skeleton_t *skeleton;
2878 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2879 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2880 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2881 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2882 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2883 dp_model_t *model = SV_GetModelByIndex(modelindex);
2888 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2889 frameblend_t frameblend[MAX_FRAMEBLENDS];
2890 matrix4x4_t blendedmatrix;
2892 PRVM_G_FLOAT(OFS_RETURN) = 0;
2893 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2895 firstbone = max(0, firstbone);
2896 lastbone = min(lastbone, model->num_bones - 1);
2897 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2898 VM_GenerateFrameGroupBlend(framegroupblend, ed);
2899 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
2900 blendfrac = 1.0f - retainfrac;
2901 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2902 frameblend[numblends].lerp *= blendfrac;
2903 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2905 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2906 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2907 for (blendindex = 0;blendindex < numblends;blendindex++)
2909 Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2910 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2912 skeleton->relativetransforms[bonenum] = blendedmatrix;
2914 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2917 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2918 static void VM_SV_skel_get_numbones(void)
2920 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2921 skeleton_t *skeleton;
2922 PRVM_G_FLOAT(OFS_RETURN) = 0;
2923 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2925 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2928 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2929 static void VM_SV_skel_get_bonename(void)
2931 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2932 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2933 skeleton_t *skeleton;
2934 PRVM_G_INT(OFS_RETURN) = 0;
2935 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2937 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2939 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(skeleton->model->data_bones[bonenum].name);
2942 // #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)
2943 static void VM_SV_skel_get_boneparent(void)
2945 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2946 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2947 skeleton_t *skeleton;
2948 PRVM_G_FLOAT(OFS_RETURN) = 0;
2949 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2951 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2953 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2956 // #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
2957 static void VM_SV_skel_find_bone(void)
2959 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2960 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2961 skeleton_t *skeleton;
2962 PRVM_G_FLOAT(OFS_RETURN) = 0;
2963 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2965 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2968 // #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)
2969 static void VM_SV_skel_get_bonerel(void)
2971 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2972 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2973 skeleton_t *skeleton;
2975 vec3_t forward, left, up, origin;
2976 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2977 VectorClear(PRVM_clientglobalvector(v_forward));
2978 VectorClear(PRVM_clientglobalvector(v_right));
2979 VectorClear(PRVM_clientglobalvector(v_up));
2980 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2982 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2984 matrix = skeleton->relativetransforms[bonenum];
2985 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2986 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2987 VectorNegate(left, PRVM_clientglobalvector(v_right));
2988 VectorCopy(up, PRVM_clientglobalvector(v_up));
2989 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2992 // #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)
2993 static void VM_SV_skel_get_boneabs(void)
2995 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2996 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2997 skeleton_t *skeleton;
3000 vec3_t forward, left, up, origin;
3001 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3002 VectorClear(PRVM_clientglobalvector(v_forward));
3003 VectorClear(PRVM_clientglobalvector(v_right));
3004 VectorClear(PRVM_clientglobalvector(v_up));
3005 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3007 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3009 matrix = skeleton->relativetransforms[bonenum];
3010 // convert to absolute
3011 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3014 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3016 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3017 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3018 VectorNegate(left, PRVM_clientglobalvector(v_right));
3019 VectorCopy(up, PRVM_clientglobalvector(v_up));
3020 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3023 // #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)
3024 static void VM_SV_skel_set_bone(void)
3026 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3027 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3028 vec3_t forward, left, up, origin;
3029 skeleton_t *skeleton;
3031 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3033 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3035 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3036 VectorNegate(PRVM_clientglobalvector(v_right), left);
3037 VectorCopy(PRVM_clientglobalvector(v_up), up);
3038 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3039 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3040 skeleton->relativetransforms[bonenum] = matrix;
3043 // #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)
3044 static void VM_SV_skel_mul_bone(void)
3046 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3047 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3048 vec3_t forward, left, up, origin;
3049 skeleton_t *skeleton;
3052 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3054 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3056 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3057 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3058 VectorNegate(PRVM_clientglobalvector(v_right), left);
3059 VectorCopy(PRVM_clientglobalvector(v_up), up);
3060 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3061 temp = skeleton->relativetransforms[bonenum];
3062 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3065 // #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)
3066 static void VM_SV_skel_mul_bones(void)
3068 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3069 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3070 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3072 vec3_t forward, left, up, origin;
3073 skeleton_t *skeleton;
3076 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3078 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3079 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3080 VectorNegate(PRVM_clientglobalvector(v_right), left);
3081 VectorCopy(PRVM_clientglobalvector(v_up), up);
3082 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3083 firstbone = max(0, firstbone);
3084 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3085 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3087 temp = skeleton->relativetransforms[bonenum];
3088 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3092 // #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
3093 static void VM_SV_skel_copybones(void)
3095 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3096 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3097 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3098 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3100 skeleton_t *skeletondst;
3101 skeleton_t *skeletonsrc;
3102 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3104 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3106 firstbone = max(0, firstbone);
3107 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3108 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3109 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3110 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3113 // #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)
3114 static void VM_SV_skel_delete(void)
3116 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3117 skeleton_t *skeleton;
3118 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3121 prog->skeletons[skeletonindex] = NULL;
3124 // #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
3125 static void VM_SV_frameforname(void)
3127 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3128 dp_model_t *model = SV_GetModelByIndex(modelindex);
3129 const char *name = PRVM_G_STRING(OFS_PARM1);
3131 PRVM_G_FLOAT(OFS_RETURN) = -1;
3132 if (!model || !model->animscenes)
3134 for (i = 0;i < model->numframes;i++)
3136 if (!strcasecmp(model->animscenes[i].name, name))
3138 PRVM_G_FLOAT(OFS_RETURN) = i;
3144 // #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.
3145 static void VM_SV_frameduration(void)
3147 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3148 dp_model_t *model = SV_GetModelByIndex(modelindex);
3149 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3150 PRVM_G_FLOAT(OFS_RETURN) = 0;
3151 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3153 if (model->animscenes[framenum].framerate)
3154 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3158 prvm_builtin_t vm_sv_builtins[] = {
3159 NULL, // #0 NULL function (not callable) (QUAKE)
3160 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3161 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3162 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3163 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3164 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3165 VM_break, // #6 void() break (QUAKE)
3166 VM_random, // #7 float() random (QUAKE)
3167 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3168 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3169 VM_error, // #10 void(string e) error (QUAKE)
3170 VM_objerror, // #11 void(string e) objerror (QUAKE)
3171 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3172 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3173 VM_spawn, // #14 entity() spawn (QUAKE)
3174 VM_remove, // #15 void(entity e) remove (QUAKE)
3175 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3176 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3177 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3178 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3179 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3180 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3181 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3182 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3183 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3184 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3185 VM_ftos, // #26 string(float f) ftos (QUAKE)
3186 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3187 VM_coredump, // #28 void() coredump (QUAKE)
3188 VM_traceon, // #29 void() traceon (QUAKE)
3189 VM_traceoff, // #30 void() traceoff (QUAKE)
3190 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3191 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3192 NULL, // #33 (QUAKE)
3193 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3194 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3195 VM_rint, // #36 float(float v) rint (QUAKE)
3196 VM_floor, // #37 float(float v) floor (QUAKE)
3197 VM_ceil, // #38 float(float v) ceil (QUAKE)
3198 NULL, // #39 (QUAKE)
3199 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3200 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3201 NULL, // #42 (QUAKE)
3202 VM_fabs, // #43 float(float f) fabs (QUAKE)
3203 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3204 VM_cvar, // #45 float(string s) cvar (QUAKE)
3205 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3206 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3207 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3208 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3209 NULL, // #50 (QUAKE)
3210 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3211 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3212 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3213 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3214 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3215 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3216 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3217 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3218 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3219 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3220 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3221 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3222 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3223 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3224 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3225 NULL, // #66 (QUAKE)
3226 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3227 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3228 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3229 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3230 NULL, // #71 (QUAKE)
3231 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3232 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3233 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3234 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3235 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3236 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3237 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3238 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3239 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3240 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3241 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3242 NULL, // #83 (QUAKE)
3243 NULL, // #84 (QUAKE)
3244 NULL, // #85 (QUAKE)
3245 NULL, // #86 (QUAKE)
3246 NULL, // #87 (QUAKE)
3247 NULL, // #88 (QUAKE)
3248 NULL, // #89 (QUAKE)
3249 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3250 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3251 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3252 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3253 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3254 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3255 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3256 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3257 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3258 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3259 // FrikaC and Telejano range #100-#199
3270 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3271 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3272 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3273 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3274 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3275 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3276 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3277 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3278 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3279 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3360 // FTEQW range #200-#299
3379 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3382 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3383 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3384 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3385 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3386 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3387 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3388 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3389 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3390 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3391 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3393 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3401 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3424 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.
3425 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
3426 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3427 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3428 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)
3429 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
3430 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)
3431 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)
3432 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)
3433 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)
3434 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)
3435 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
3436 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)
3437 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
3438 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.
3461 // CSQC range #300-#399
3462 NULL, // #300 void() clearscene (EXT_CSQC)
3463 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3464 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3465 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3466 NULL, // #304 void() renderscene (EXT_CSQC)
3467 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3468 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3469 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3470 NULL, // #308 void() R_EndPolygon
3472 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3473 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3477 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3478 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3479 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3480 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3481 NULL, // #319 void(string name) freepic (EXT_CSQC)
3482 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3483 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3484 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3485 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3486 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3487 NULL, // #325 void(void) drawresetcliparea
3492 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3493 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3494 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3495 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3496 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3497 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3498 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3499 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3500 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3501 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3502 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3503 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3504 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3505 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3506 NULL, // #344 vector() getmousepos (EXT_CSQC)
3507 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3508 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3509 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3510 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3511 NULL, // #349 float() isdemo (EXT_CSQC)
3512 VM_isserver, // #350 float() isserver (EXT_CSQC)
3513 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3514 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3515 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3516 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3522 NULL, // #360 float() readbyte (EXT_CSQC)
3523 NULL, // #361 float() readchar (EXT_CSQC)
3524 NULL, // #362 float() readshort (EXT_CSQC)
3525 NULL, // #363 float() readlong (EXT_CSQC)
3526 NULL, // #364 float() readcoord (EXT_CSQC)
3527 NULL, // #365 float() readangle (EXT_CSQC)
3528 NULL, // #366 string() readstring (EXT_CSQC)
3529 NULL, // #367 float() readfloat (EXT_CSQC)
3562 // LordHavoc's range #400-#499
3563 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3564 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3565 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3566 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3567 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3568 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3569 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3570 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3571 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)
3572 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3573 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3574 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3575 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3576 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3577 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3578 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3579 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3580 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3581 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3582 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3583 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3584 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3585 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3586 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3587 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3588 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3589 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3590 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3591 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3592 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3593 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3594 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3595 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3596 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3597 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3598 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3599 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3600 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3601 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3602 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3603 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3604 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3605 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3606 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3607 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3608 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3609 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3610 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3611 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3612 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3613 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3614 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3615 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3616 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3617 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3618 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3619 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3620 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3622 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3623 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3624 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3625 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3626 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3627 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3628 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3629 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3630 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3631 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3632 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3634 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3635 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3636 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3637 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3638 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3639 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3640 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3641 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3642 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3643 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3644 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3645 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3646 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3647 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3648 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3649 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3657 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3658 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3659 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3660 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3661 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3662 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3663 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3664 VM_SV_WritePicture, // #501
3666 VM_whichpack, // #503 string(string) whichpack = #503;
3673 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3674 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3675 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3676 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)
3677 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3678 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3679 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3680 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3681 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3682 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3692 VM_loadfromdata, // #529
3693 VM_loadfromfile, // #530
3694 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3696 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3697 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3703 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3704 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3705 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3768 VM_callfunction, // #605
3769 VM_writetofile, // #606
3770 VM_isfunction, // #607
3776 VM_parseentitydata, // #613
3787 VM_SV_getextresponse, // #624 string getextresponse(void)
3790 VM_sprintf, // #627 string sprintf(string format, ...)
3791 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3792 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3802 VM_digest_hex, // #639
3806 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3808 void VM_SV_Cmd_Init(void)
3813 void VM_SV_Cmd_Reset(void)
3815 World_End(&sv.world);
3816 if(PRVM_serverfunction(SV_Shutdown))
3818 func_t s = PRVM_serverfunction(SV_Shutdown);
3819 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3820 PRVM_ExecuteProgram(s,"SV_Shutdown() required");