6 //============================================================================
11 const char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
24 "DP_CSQC_ENTITYWORLDOBJECT "
25 "DP_CSQC_ENTITYMODELLIGHT "
26 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
27 "DP_CSQC_MULTIFRAME_INTERPOLATION "
28 "DP_CSQC_BOXPARTICLES "
29 "DP_CSQC_SPAWNPARTICLE "
30 "DP_CSQC_QUERYRENDERENTITY "
31 "DP_CSQC_ROTATEMOVES "
44 "DP_EF_RESTARTANIM_BIT "
49 "DP_ENT_CUSTOMCOLORMAP "
50 "DP_ENT_EXTERIORMODELTOCLIENT "
53 "DP_ENT_LOWPRECISION "
55 "DP_ENT_TRAILEFFECTNUM "
58 "DP_GFX_EXTERNALTEXTURES "
59 "DP_GFX_EXTERNALTEXTURES_PERMAP "
61 "DP_GFX_MODEL_INTERPOLATION "
62 "DP_GFX_QUAKE3MODELTAGS "
66 "DP_GFX_FONTS_FREETYPE "
68 "DP_FONT_VARIABLEWIDTH "
70 "DP_HALFLIFE_MAP_CVAR "
73 "DP_LIGHTSTYLE_STATICVALUE "
77 "DP_MOVETYPEBOUNCEMISSILE "
78 "DP_MOVETYPEFLYWORLDONLY "
81 "DP_QC_ASINACOSATANATAN2TAN "
87 "DP_QC_CVAR_DEFSTRING "
88 "DP_QC_CVAR_DESCRIPTION "
95 "DP_QC_EXTRESPONSEPACKET "
97 "DP_QC_FINDCHAINFLAGS "
98 "DP_QC_FINDCHAINFLOAT "
99 "DP_QC_FINDCHAIN_TOFIELD "
105 "DP_QC_GETSURFACETRIANGLE "
106 "DP_QC_GETSURFACEPOINTATTRIBUTE "
108 "DP_QC_GETTAGINFO_BONEPROPERTIES "
110 "DP_QC_GETTIME_CDTRACK "
113 "DP_QC_MULTIPLETEMPSTRINGS "
114 "DP_QC_NUM_FOR_EDICT "
116 "DP_QC_SINCOSSQRTPOW "
119 "DP_QC_STRINGBUFFERS "
120 "DP_QC_STRINGBUFFERS_CVARLIST "
121 "DP_QC_STRINGCOLORFUNCTIONS "
122 "DP_QC_STRING_CASE_FUNCTIONS "
124 "DP_QC_TOKENIZEBYSEPARATOR "
125 "DP_QC_TOKENIZE_CONSOLE "
128 "DP_QC_TRACE_MOVETYPE_HITMODEL "
129 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
130 "DP_QC_UNLIMITEDTEMPSTRINGS "
134 "DP_QC_VECTOANGLES_WITH_ROLL "
135 "DP_QC_VECTORVECTORS "
142 "DP_SKELETONOBJECTS "
143 "DP_SND_DIRECTIONLESSATTNNONE "
145 "DP_SND_SOUND7_WIP1 "
146 "DP_SND_SOUND7_WIP2 "
150 "DP_SND_GETSOUNDTIME "
152 "DP_VIDEO_SUBTITLES "
156 "DP_SV_BOUNCEFACTOR "
157 "DP_SV_CLIENTCAMERA "
158 "DP_SV_CLIENTCOLORS "
161 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
162 "DP_SV_DISCARDABLEDEMO "
163 "DP_SV_DRAWONLYTOCLIENT "
166 "DP_SV_ENTITYCONTENTSTRANSITION "
167 "DP_SV_MODELFLAGS_AS_EFFECTS "
168 "DP_SV_MOVETYPESTEP_LANDEVENT "
170 "DP_SV_NODRAWTOCLIENT "
171 "DP_SV_ONENTITYNOSPAWNFUNCTION "
172 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
174 "DP_SV_PING_PACKETLOSS "
175 "DP_SV_PLAYERPHYSICS "
177 "DP_SV_POINTPARTICLES "
179 "DP_SV_PRECACHEANYTIME "
183 "DP_SV_ROTATINGBMODEL "
187 "DP_SV_SPAWNFUNC_PREFIX "
188 "DP_SV_WRITEPICTURE "
189 "DP_SV_WRITEUNTERMINATEDSTRING "
193 "DP_TE_EXPLOSIONRGB "
195 "DP_TE_PARTICLECUBE "
196 "DP_TE_PARTICLERAIN "
197 "DP_TE_PARTICLESNOW "
199 "DP_TE_QUADEFFECTS1 "
202 "DP_TE_STANDARDEFFECTBUILTINS "
203 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
207 "FTE_CSQC_SKELETONOBJECTS "
210 "KRIMZON_SV_PARSECLIENTCOMMAND "
213 "NEXUIZ_PLAYERMODEL "
215 "PRYDON_CLIENTCURSOR "
216 "TENEBRAE_GFX_DLIGHTS "
219 //"EXT_CSQC " // not ready yet
226 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.
228 setorigin (entity, origin)
231 static void VM_SV_setorigin (void)
236 VM_SAFEPARMCOUNT(2, VM_setorigin);
238 e = PRVM_G_EDICT(OFS_PARM0);
239 if (e == prog->edicts)
241 VM_Warning("setorigin: can not modify world entity\n");
244 if (e->priv.server->free)
246 VM_Warning("setorigin: can not modify free entity\n");
249 org = PRVM_G_VECTOR(OFS_PARM1);
250 VectorCopy (org, PRVM_serveredictvector(e, origin));
254 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
255 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
259 for (i=0 ; i<3 ; i++)
261 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
263 // set derived values
264 VectorCopy (min, PRVM_serveredictvector(e, mins));
265 VectorCopy (max, PRVM_serveredictvector(e, maxs));
266 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
275 the size box is rotated by the current angle
276 LordHavoc: no it isn't...
278 setsize (entity, minvector, maxvector)
281 static void VM_SV_setsize (void)
286 VM_SAFEPARMCOUNT(3, VM_setsize);
288 e = PRVM_G_EDICT(OFS_PARM0);
289 if (e == prog->edicts)
291 VM_Warning("setsize: can not modify world entity\n");
294 if (e->priv.server->free)
296 VM_Warning("setsize: can not modify free entity\n");
299 min = PRVM_G_VECTOR(OFS_PARM1);
300 max = PRVM_G_VECTOR(OFS_PARM2);
301 SetMinMaxSize (e, min, max, false);
309 setmodel(entity, model)
312 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
313 static void VM_SV_setmodel (void)
319 VM_SAFEPARMCOUNT(2, VM_setmodel);
321 e = PRVM_G_EDICT(OFS_PARM0);
322 if (e == prog->edicts)
324 VM_Warning("setmodel: can not modify world entity\n");
327 if (e->priv.server->free)
329 VM_Warning("setmodel: can not modify free entity\n");
332 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
333 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
334 PRVM_serveredictfloat(e, modelindex) = i;
336 mod = SV_GetModelByIndex(i);
340 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
341 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
343 SetMinMaxSize (e, quakemins, quakemaxs, true);
346 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
353 single print to a specific client
355 sprint(clientent, value)
358 static void VM_SV_sprint (void)
362 char string[VM_STRINGTEMP_LENGTH];
364 VM_VarString(1, string, sizeof(string));
366 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
368 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
369 // LordHavoc: div0 requested that sprintto world operate like print
376 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
378 VM_Warning("tried to centerprint to a non-client\n");
382 client = svs.clients + entnum-1;
383 if (!client->netconnection)
386 MSG_WriteChar(&client->netconnection->message,svc_print);
387 MSG_WriteString(&client->netconnection->message, string);
395 single print to a specific client
397 centerprint(clientent, value)
400 static void VM_SV_centerprint (void)
404 char string[VM_STRINGTEMP_LENGTH];
406 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
408 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
410 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
412 VM_Warning("tried to centerprint to a non-client\n");
416 client = svs.clients + entnum-1;
417 if (!client->netconnection)
420 VM_VarString(1, string, sizeof(string));
421 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
422 MSG_WriteString(&client->netconnection->message, string);
429 particle(origin, color, count)
432 static void VM_SV_particle (void)
438 VM_SAFEPARMCOUNT(4, VM_SV_particle);
440 org = PRVM_G_VECTOR(OFS_PARM0);
441 dir = PRVM_G_VECTOR(OFS_PARM1);
442 color = PRVM_G_FLOAT(OFS_PARM2);
443 count = PRVM_G_FLOAT(OFS_PARM3);
444 SV_StartParticle (org, dir, (int)color, (int)count);
454 static void VM_SV_ambientsound (void)
458 float vol, attenuation;
461 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
463 pos = PRVM_G_VECTOR (OFS_PARM0);
464 samp = PRVM_G_STRING(OFS_PARM1);
465 vol = PRVM_G_FLOAT(OFS_PARM2);
466 attenuation = PRVM_G_FLOAT(OFS_PARM3);
468 // check to see if samp was properly precached
469 soundnum = SV_SoundIndex(samp, 1);
477 // add an svc_spawnambient command to the level signon packet
480 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
482 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
484 MSG_WriteVector(&sv.signon, pos, sv.protocol);
486 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
487 MSG_WriteShort (&sv.signon, soundnum);
489 MSG_WriteByte (&sv.signon, soundnum);
491 MSG_WriteByte (&sv.signon, (int)(vol*255));
492 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
500 Each entity can have eight independant sound sources, like voice,
503 Channel 0 is an auto-allocate channel, the others override anything
504 already running on that entity/channel pair.
506 An attenuation of 0 will play full volume everywhere in the level.
507 Larger attenuations will drop off.
511 static void VM_SV_sound (void)
515 prvm_edict_t *entity;
521 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
523 entity = PRVM_G_EDICT(OFS_PARM0);
524 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
525 sample = PRVM_G_STRING(OFS_PARM2);
526 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
529 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
533 attenuation = PRVM_G_FLOAT(OFS_PARM4);
537 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
542 if(channel >= 8 && channel <= 15) // weird QW feature
544 flags |= CHANFLAG_RELIABLE;
549 flags = PRVM_G_FLOAT(OFS_PARM6);
551 if (volume < 0 || volume > 255)
553 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
557 if (attenuation < 0 || attenuation > 4)
559 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
563 channel = CHAN_USER2ENGINE(channel);
565 if (!IS_CHAN(channel))
567 VM_Warning("SV_StartSound: channel must be in range 0-127\n");
571 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE, pitchchange);
578 Follows the same logic as VM_SV_sound, except instead of
579 an entity, an origin for the sound is provided, and channel
580 is omitted (since no entity is being tracked).
584 static void VM_SV_pointsound(void)
592 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
594 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
595 sample = PRVM_G_STRING(OFS_PARM1);
596 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
597 attenuation = PRVM_G_FLOAT(OFS_PARM3);
598 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
600 if (volume < 0 || volume > 255)
602 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
606 if (attenuation < 0 || attenuation > 4)
608 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
612 SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
619 Used for use tracing and shot targeting
620 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
621 if the tryents flag is set.
623 traceline (vector1, vector2, movetype, ignore)
626 static void VM_SV_traceline (void)
633 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
635 prog->xfunction->builtinsprofile += 30;
637 v1 = PRVM_G_VECTOR(OFS_PARM0);
638 v2 = PRVM_G_VECTOR(OFS_PARM1);
639 move = (int)PRVM_G_FLOAT(OFS_PARM2);
640 ent = PRVM_G_EDICT(OFS_PARM3);
642 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]))
643 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));
645 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
647 VM_SetTraceGlobals(&trace);
655 Used for use tracing and shot targeting
656 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
657 if the tryents flag is set.
659 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
662 // LordHavoc: added this for my own use, VERY useful, similar to traceline
663 static void VM_SV_tracebox (void)
665 float *v1, *v2, *m1, *m2;
670 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
672 prog->xfunction->builtinsprofile += 30;
674 v1 = PRVM_G_VECTOR(OFS_PARM0);
675 m1 = PRVM_G_VECTOR(OFS_PARM1);
676 m2 = PRVM_G_VECTOR(OFS_PARM2);
677 v2 = PRVM_G_VECTOR(OFS_PARM3);
678 move = (int)PRVM_G_FLOAT(OFS_PARM4);
679 ent = PRVM_G_EDICT(OFS_PARM5);
681 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]))
682 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));
684 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
686 VM_SetTraceGlobals(&trace);
689 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
694 vec3_t original_origin;
695 vec3_t original_velocity;
696 vec3_t original_angles;
697 vec3_t original_avelocity;
700 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
701 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
702 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
703 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
705 gravity = PRVM_serveredictfloat(tossent, gravity);
708 gravity *= sv_gravity.value * 0.025;
710 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
712 SV_CheckVelocity (tossent);
713 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
714 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
715 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
716 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
717 trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
718 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
719 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
721 if (trace.fraction < 1)
725 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
726 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
727 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
728 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
733 static void VM_SV_tracetoss (void)
737 prvm_edict_t *ignore;
739 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
741 prog->xfunction->builtinsprofile += 600;
743 ent = PRVM_G_EDICT(OFS_PARM0);
744 if (ent == prog->edicts)
746 VM_Warning("tracetoss: can not use world entity\n");
749 ignore = PRVM_G_EDICT(OFS_PARM1);
751 trace = SV_Trace_Toss (ent, ignore);
753 VM_SetTraceGlobals(&trace);
756 //============================================================================
758 static int checkpvsbytes;
759 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
761 static int VM_SV_newcheckclient (int check)
767 // cycle to the next one
769 check = bound(1, check, svs.maxclients);
770 if (check == svs.maxclients)
778 prog->xfunction->builtinsprofile++;
780 if (i == svs.maxclients+1)
782 // look up the client's edict
783 ent = PRVM_EDICT_NUM(i);
784 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
785 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
787 // found a valid client (possibly the same one again)
791 // get the PVS for the entity
792 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
794 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
795 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
804 Returns a client (or object that has a client enemy) that would be a
807 If there is more than one valid option, they are cycled each frame
809 If (self.origin + self.viewofs) is not in the PVS of the current target,
810 it is not returned at all.
815 int c_invis, c_notvis;
816 static void VM_SV_checkclient (void)
818 prvm_edict_t *ent, *self;
821 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
823 // find a new check if on a new frame
824 if (sv.time - sv.lastchecktime >= 0.1)
826 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
827 sv.lastchecktime = sv.time;
830 // return check if it might be visible
831 ent = PRVM_EDICT_NUM(sv.lastcheck);
832 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
834 VM_RETURN_EDICT(prog->edicts);
838 // if current entity can't possibly see the check entity, return 0
839 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
840 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
841 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
844 VM_RETURN_EDICT(prog->edicts);
848 // might be able to see it
850 VM_RETURN_EDICT(ent);
853 //============================================================================
859 Checks if an entity is in a point's PVS.
860 Should be fast but can be inexact.
862 float checkpvs(vector viewpos, entity viewee) = #240;
865 static void VM_SV_checkpvs (void)
868 prvm_edict_t *viewee;
873 unsigned char fatpvs[MAX_MAP_LEAFS/8];
876 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
877 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
878 viewee = PRVM_G_EDICT(OFS_PARM1);
880 if(viewee->priv.server->free)
882 VM_Warning("checkpvs: can not check free entity\n");
883 PRVM_G_FLOAT(OFS_RETURN) = 4;
888 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
890 // no PVS support on this worldmodel... darn
891 PRVM_G_FLOAT(OFS_RETURN) = 3;
894 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
897 // viewpos isn't in any PVS... darn
898 PRVM_G_FLOAT(OFS_RETURN) = 2;
901 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
903 // using fat PVS like FTEQW does (slow)
904 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
906 // no PVS support on this worldmodel... darn
907 PRVM_G_FLOAT(OFS_RETURN) = 3;
910 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
913 // viewpos isn't in any PVS... darn
914 PRVM_G_FLOAT(OFS_RETURN) = 2;
917 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
926 Sends text over to the client's execution buffer
928 stuffcmd (clientent, value, ...)
931 static void VM_SV_stuffcmd (void)
935 char string[VM_STRINGTEMP_LENGTH];
937 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
939 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
940 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
942 VM_Warning("Can't stuffcmd to a non-client\n");
946 VM_VarString(1, string, sizeof(string));
949 host_client = svs.clients + entnum-1;
950 Host_ClientCommands ("%s", string);
958 Returns a chain of entities that have origins within a spherical area
960 findradius (origin, radius)
963 static void VM_SV_findradius (void)
965 prvm_edict_t *ent, *chain;
966 vec_t radius, radius2;
967 vec3_t org, eorg, mins, maxs;
970 static prvm_edict_t *touchedicts[MAX_EDICTS];
973 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
976 chainfield = PRVM_G_INT(OFS_PARM2);
978 chainfield = prog->fieldoffsets.chain;
980 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
982 chain = (prvm_edict_t *)prog->edicts;
984 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
985 radius = PRVM_G_FLOAT(OFS_PARM1);
986 radius2 = radius * radius;
988 mins[0] = org[0] - (radius + 1);
989 mins[1] = org[1] - (radius + 1);
990 mins[2] = org[2] - (radius + 1);
991 maxs[0] = org[0] + (radius + 1);
992 maxs[1] = org[1] + (radius + 1);
993 maxs[2] = org[2] + (radius + 1);
994 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
995 if (numtouchedicts > MAX_EDICTS)
997 // this never happens
998 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
999 numtouchedicts = MAX_EDICTS;
1001 for (i = 0;i < numtouchedicts;i++)
1003 ent = touchedicts[i];
1004 prog->xfunction->builtinsprofile++;
1005 // Quake did not return non-solid entities but darkplaces does
1006 // (note: this is the reason you can't blow up fallen zombies)
1007 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1009 // LordHavoc: compare against bounding box rather than center so it
1010 // doesn't miss large objects, and use DotProduct instead of Length
1011 // for a major speedup
1012 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1013 if (sv_gameplayfix_findradiusdistancetobox.integer)
1015 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1016 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1017 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1020 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1021 if (DotProduct(eorg, eorg) < radius2)
1023 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1028 VM_RETURN_EDICT(chain);
1031 static void VM_SV_precache_sound (void)
1033 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1034 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1037 static void VM_SV_precache_model (void)
1039 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1040 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1041 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1048 float(float yaw, float dist[, settrace]) walkmove
1051 static void VM_SV_walkmove (void)
1060 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1062 // assume failure if it returns early
1063 PRVM_G_FLOAT(OFS_RETURN) = 0;
1065 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1066 if (ent == prog->edicts)
1068 VM_Warning("walkmove: can not modify world entity\n");
1071 if (ent->priv.server->free)
1073 VM_Warning("walkmove: can not modify free entity\n");
1076 yaw = PRVM_G_FLOAT(OFS_PARM0);
1077 dist = PRVM_G_FLOAT(OFS_PARM1);
1078 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1080 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1083 yaw = yaw*M_PI*2 / 360;
1085 move[0] = cos(yaw)*dist;
1086 move[1] = sin(yaw)*dist;
1089 // save program state, because SV_movestep may call other progs
1090 oldf = prog->xfunction;
1091 oldself = PRVM_serverglobaledict(self);
1093 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1096 // restore program state
1097 prog->xfunction = oldf;
1098 PRVM_serverglobaledict(self) = oldself;
1109 static void VM_SV_droptofloor (void)
1115 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1117 // assume failure if it returns early
1118 PRVM_G_FLOAT(OFS_RETURN) = 0;
1120 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1121 if (ent == prog->edicts)
1123 VM_Warning("droptofloor: can not modify world entity\n");
1126 if (ent->priv.server->free)
1128 VM_Warning("droptofloor: can not modify free entity\n");
1132 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1135 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1136 if (sv_gameplayfix_unstickentities.integer)
1137 SV_UnstickEntity(ent);
1139 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1140 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1143 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]);
1144 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1145 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1146 VectorSubtract(trace.endpos, offset, trace.endpos);
1147 if (trace.startsolid)
1149 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]);
1150 if (sv_gameplayfix_unstickentities.integer)
1151 SV_UnstickEntity(ent);
1153 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1154 PRVM_serveredictedict(ent, groundentity) = 0;
1155 PRVM_G_FLOAT(OFS_RETURN) = 1;
1157 else if (trace.fraction < 1)
1159 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]);
1160 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1161 if (sv_gameplayfix_unstickentities.integer)
1162 SV_UnstickEntity(ent);
1164 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1165 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1166 PRVM_G_FLOAT(OFS_RETURN) = 1;
1167 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1168 ent->priv.server->suspendedinairflag = true;
1173 if (trace.fraction != 1)
1175 if (trace.fraction < 1)
1176 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1178 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1179 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1180 PRVM_G_FLOAT(OFS_RETURN) = 1;
1181 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1182 ent->priv.server->suspendedinairflag = true;
1191 void(float style, string value) lightstyle
1194 static void VM_SV_lightstyle (void)
1201 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1203 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1204 val = PRVM_G_STRING(OFS_PARM1);
1206 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1207 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1210 // change the string in sv
1211 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1213 // send message to all clients on this server
1214 if (sv.state != ss_active)
1217 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1219 if (client->active && client->netconnection)
1221 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1222 MSG_WriteChar (&client->netconnection->message,style);
1223 MSG_WriteString (&client->netconnection->message, val);
1233 static void VM_SV_checkbottom (void)
1235 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1236 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1244 static void VM_SV_pointcontents (void)
1246 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1247 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1254 Pick a vector for the player to shoot along
1255 vector aim(entity, missilespeed)
1258 static void VM_SV_aim (void)
1260 prvm_edict_t *ent, *check, *bestent;
1261 vec3_t start, dir, end, bestdir;
1264 float dist, bestdist;
1267 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1269 // assume failure if it returns early
1270 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1271 // if sv_aim is so high it can't possibly accept anything, skip out early
1272 if (sv_aim.value >= 1)
1275 ent = PRVM_G_EDICT(OFS_PARM0);
1276 if (ent == prog->edicts)
1278 VM_Warning("aim: can not use world entity\n");
1281 if (ent->priv.server->free)
1283 VM_Warning("aim: can not use free entity\n");
1286 //speed = PRVM_G_FLOAT(OFS_PARM1);
1288 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1291 // try sending a trace straight
1292 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1293 VectorMA (start, 2048, dir, end);
1294 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1295 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1296 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1298 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1303 // try all possible entities
1304 VectorCopy (dir, bestdir);
1305 bestdist = sv_aim.value;
1308 check = PRVM_NEXT_EDICT(prog->edicts);
1309 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1311 prog->xfunction->builtinsprofile++;
1312 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1316 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1317 continue; // don't aim at teammate
1318 for (j=0 ; j<3 ; j++)
1319 end[j] = PRVM_serveredictvector(check, origin)[j]
1320 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1321 VectorSubtract (end, start, dir);
1322 VectorNormalize (dir);
1323 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1324 if (dist < bestdist)
1325 continue; // to far to turn
1326 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1327 if (tr.ent == check)
1328 { // can shoot at this one
1336 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1337 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1338 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1340 VectorNormalize (end);
1341 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1345 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1350 ===============================================================================
1354 ===============================================================================
1357 #define MSG_BROADCAST 0 // unreliable to all
1358 #define MSG_ONE 1 // reliable to one (msg_entity)
1359 #define MSG_ALL 2 // reliable to all
1360 #define MSG_INIT 3 // write to the init string
1361 #define MSG_ENTITY 5
1363 sizebuf_t *WriteDest (void)
1369 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1373 return &sv.datagram;
1376 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1377 entnum = PRVM_NUM_FOR_EDICT(ent);
1378 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1380 VM_Warning ("WriteDest: tried to write to non-client\n");
1381 return &sv.reliable_datagram;
1384 return &svs.clients[entnum-1].netconnection->message;
1387 VM_Warning ("WriteDest: bad destination\n");
1389 return &sv.reliable_datagram;
1395 return sv.writeentitiestoclient_msg;
1401 static void VM_SV_WriteByte (void)
1403 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1404 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1407 static void VM_SV_WriteChar (void)
1409 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1410 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1413 static void VM_SV_WriteShort (void)
1415 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1416 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1419 static void VM_SV_WriteLong (void)
1421 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1422 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1425 static void VM_SV_WriteAngle (void)
1427 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1428 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1431 static void VM_SV_WriteCoord (void)
1433 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1434 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1437 static void VM_SV_WriteString (void)
1439 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1440 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1443 static void VM_SV_WriteUnterminatedString (void)
1445 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1446 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1450 static void VM_SV_WriteEntity (void)
1452 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1453 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1456 // writes a picture as at most size bytes of data
1458 // IMGNAME \0 SIZE(short) IMGDATA
1459 // if failed to read/compress:
1461 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1462 static void VM_SV_WritePicture (void)
1464 const char *imgname;
1468 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1470 imgname = PRVM_G_STRING(OFS_PARM1);
1471 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1475 MSG_WriteString(WriteDest(), imgname);
1476 if(Image_Compress(imgname, size, &buf, &size))
1479 MSG_WriteShort(WriteDest(), size);
1480 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1485 MSG_WriteShort(WriteDest(), 0);
1489 //////////////////////////////////////////////////////////
1491 static void VM_SV_makestatic (void)
1496 // allow 0 parameters due to an id1 qc bug in which this function is used
1497 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1498 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1500 if (prog->argc >= 1)
1501 ent = PRVM_G_EDICT(OFS_PARM0);
1503 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1504 if (ent == prog->edicts)
1506 VM_Warning("makestatic: can not modify world entity\n");
1509 if (ent->priv.server->free)
1511 VM_Warning("makestatic: can not modify free entity\n");
1516 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1521 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1522 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1523 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1525 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1527 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1528 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1529 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1533 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1534 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1535 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1538 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1539 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1540 for (i=0 ; i<3 ; i++)
1542 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1543 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1546 // throw the entity away now
1550 //=============================================================================
1557 static void VM_SV_setspawnparms (void)
1563 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1565 ent = PRVM_G_EDICT(OFS_PARM0);
1566 i = PRVM_NUM_FOR_EDICT(ent);
1567 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1569 Con_Print("tried to setspawnparms on a non-client\n");
1573 // copy spawn parms out of the client_t
1574 client = svs.clients + i-1;
1575 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1576 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1583 Returns a color vector indicating the lighting at the requested point.
1585 (Internal Operation note: actually measures the light beneath the point, just like
1586 the model lighting on the client)
1591 static void VM_SV_getlight (void)
1593 vec3_t ambientcolor, diffusecolor, diffusenormal;
1595 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1596 p = PRVM_G_VECTOR(OFS_PARM0);
1597 VectorClear(ambientcolor);
1598 VectorClear(diffusecolor);
1599 VectorClear(diffusenormal);
1600 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1601 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1602 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1607 unsigned char type; // 1/2/8 or other value if isn't used
1611 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1612 static int vm_customstats_last;
1614 void VM_CustomStats_Clear (void)
1618 Z_Free(vm_customstats);
1619 vm_customstats = NULL;
1620 vm_customstats_last = -1;
1624 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1632 for(i=0; i<vm_customstats_last+1 ;i++)
1634 if(!vm_customstats[i].type)
1636 switch(vm_customstats[i].type)
1638 //string as 16 bytes
1641 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1642 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1643 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1644 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1645 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1647 //float field sent as-is
1649 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1651 //integer value of float field
1653 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1661 // void(float index, float type, .void field) SV_AddStat = #232;
1662 // Set up an auto-sent player stat.
1663 // Client's get thier own fields sent to them. Index may not be less than 32.
1664 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1665 // 1: string (4 stats carrying a total of 16 charactures)
1666 // 2: float (one stat, float converted to an integer for transportation)
1667 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1668 static void VM_SV_AddStat (void)
1673 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1677 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1680 VM_Warning("PF_SV_AddStat: not enough memory\n");
1684 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1685 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1686 off = PRVM_G_INT (OFS_PARM2);
1691 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1694 if(i >= (MAX_CL_STATS-32))
1696 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1699 if(i > (MAX_CL_STATS-32-4) && type == 1)
1701 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1704 vm_customstats[i].type = type;
1705 vm_customstats[i].fieldoffset = off;
1706 if(vm_customstats_last < i)
1707 vm_customstats_last = i;
1714 copies data from one entity to another
1716 copyentity(src, dst)
1719 static void VM_SV_copyentity (void)
1721 prvm_edict_t *in, *out;
1722 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1723 in = PRVM_G_EDICT(OFS_PARM0);
1724 if (in == prog->edicts)
1726 VM_Warning("copyentity: can not read world entity\n");
1729 if (in->priv.server->free)
1731 VM_Warning("copyentity: can not read free entity\n");
1734 out = PRVM_G_EDICT(OFS_PARM1);
1735 if (out == prog->edicts)
1737 VM_Warning("copyentity: can not modify world entity\n");
1740 if (out->priv.server->free)
1742 VM_Warning("copyentity: can not modify free entity\n");
1745 memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
1754 sets the color of a client and broadcasts the update to all connected clients
1756 setcolor(clientent, value)
1759 static void VM_SV_setcolor (void)
1764 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1765 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1766 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1768 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1770 Con_Print("tried to setcolor a non-client\n");
1774 client = svs.clients + entnum-1;
1777 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1778 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1781 if (client->old_colors != client->colors)
1783 client->old_colors = client->colors;
1784 // send notification to all clients
1785 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1786 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1787 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1795 effect(origin, modelname, startframe, framecount, framerate)
1798 static void VM_SV_effect (void)
1802 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1803 s = PRVM_G_STRING(OFS_PARM1);
1806 VM_Warning("effect: no model specified\n");
1810 i = SV_ModelIndex(s, 1);
1813 VM_Warning("effect: model not precached\n");
1817 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1819 VM_Warning("effect: framecount < 1\n");
1823 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1825 VM_Warning("effect: framerate < 1\n");
1829 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));
1832 static void VM_SV_te_blood (void)
1834 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1835 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1837 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1838 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1840 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1841 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1842 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1844 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1845 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1846 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1848 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1849 SV_FlushBroadcastMessages();
1852 static void VM_SV_te_bloodshower (void)
1854 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1855 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1857 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1858 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1860 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1861 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1862 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1864 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1865 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1866 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1868 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1870 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1871 SV_FlushBroadcastMessages();
1874 static void VM_SV_te_explosionrgb (void)
1876 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1877 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1878 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1880 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1881 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1882 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1884 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1885 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1886 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1887 SV_FlushBroadcastMessages();
1890 static void VM_SV_te_particlecube (void)
1892 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1893 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1895 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1896 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1900 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1910 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1912 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1913 // gravity true/false
1914 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1916 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1917 SV_FlushBroadcastMessages();
1920 static void VM_SV_te_particlerain (void)
1922 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1923 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1925 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1926 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1934 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1936 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1940 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1942 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1943 SV_FlushBroadcastMessages();
1946 static void VM_SV_te_particlesnow (void)
1948 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1949 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1951 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1952 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1954 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1955 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1964 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1966 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1968 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1969 SV_FlushBroadcastMessages();
1972 static void VM_SV_te_spark (void)
1974 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1975 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1977 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1978 MSG_WriteByte(&sv.datagram, TE_SPARK);
1980 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1984 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1985 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1986 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1988 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1989 SV_FlushBroadcastMessages();
1992 static void VM_SV_te_gunshotquad (void)
1994 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1995 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1996 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1998 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1999 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2000 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2001 SV_FlushBroadcastMessages();
2004 static void VM_SV_te_spikequad (void)
2006 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2007 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2008 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2010 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2011 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2012 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2013 SV_FlushBroadcastMessages();
2016 static void VM_SV_te_superspikequad (void)
2018 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2019 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2020 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2022 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2023 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2024 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2025 SV_FlushBroadcastMessages();
2028 static void VM_SV_te_explosionquad (void)
2030 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2031 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2032 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2034 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2035 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2036 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2037 SV_FlushBroadcastMessages();
2040 static void VM_SV_te_smallflash (void)
2042 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2043 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2044 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2046 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2047 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2048 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2049 SV_FlushBroadcastMessages();
2052 static void VM_SV_te_customflash (void)
2054 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2055 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2057 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2058 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2060 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2061 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2062 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2064 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2066 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2068 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2069 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2070 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2071 SV_FlushBroadcastMessages();
2074 static void VM_SV_te_gunshot (void)
2076 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2077 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2078 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2080 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2081 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2082 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2083 SV_FlushBroadcastMessages();
2086 static void VM_SV_te_spike (void)
2088 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2089 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2090 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2092 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2093 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2094 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2095 SV_FlushBroadcastMessages();
2098 static void VM_SV_te_superspike (void)
2100 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2101 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2102 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2104 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2105 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2106 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2107 SV_FlushBroadcastMessages();
2110 static void VM_SV_te_explosion (void)
2112 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2113 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2114 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2116 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2117 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2118 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2119 SV_FlushBroadcastMessages();
2122 static void VM_SV_te_tarexplosion (void)
2124 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2125 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2126 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2128 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2129 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2130 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2131 SV_FlushBroadcastMessages();
2134 static void VM_SV_te_wizspike (void)
2136 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2137 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2138 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2140 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2141 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2142 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2143 SV_FlushBroadcastMessages();
2146 static void VM_SV_te_knightspike (void)
2148 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2149 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2150 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2152 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2153 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2154 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2155 SV_FlushBroadcastMessages();
2158 static void VM_SV_te_lavasplash (void)
2160 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2161 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2162 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2164 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2165 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2166 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2167 SV_FlushBroadcastMessages();
2170 static void VM_SV_te_teleport (void)
2172 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2173 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2174 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2176 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2177 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2178 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2179 SV_FlushBroadcastMessages();
2182 static void VM_SV_te_explosion2 (void)
2184 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2185 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2186 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2188 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2189 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2190 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2192 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2193 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2194 SV_FlushBroadcastMessages();
2197 static void VM_SV_te_lightning1 (void)
2199 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2200 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2201 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2203 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2205 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2206 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2207 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2209 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2210 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2211 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2212 SV_FlushBroadcastMessages();
2215 static void VM_SV_te_lightning2 (void)
2217 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2218 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2219 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2221 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2223 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2224 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2225 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2227 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2230 SV_FlushBroadcastMessages();
2233 static void VM_SV_te_lightning3 (void)
2235 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2236 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2237 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2239 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2241 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2242 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2243 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2245 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2246 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2247 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2248 SV_FlushBroadcastMessages();
2251 static void VM_SV_te_beam (void)
2253 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2254 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2255 MSG_WriteByte(&sv.datagram, TE_BEAM);
2257 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2259 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2260 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2261 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2263 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2264 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2265 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2266 SV_FlushBroadcastMessages();
2269 static void VM_SV_te_plasmaburn (void)
2271 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2272 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2273 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2274 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2275 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2276 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2277 SV_FlushBroadcastMessages();
2280 static void VM_SV_te_flamejet (void)
2282 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2283 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2284 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2286 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2287 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2288 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2290 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2291 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2292 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2294 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2295 SV_FlushBroadcastMessages();
2298 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2299 //this function originally written by KrimZon, made shorter by LordHavoc
2300 static void VM_SV_clientcommand (void)
2302 client_t *temp_client;
2304 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2306 //find client for this entity
2307 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2308 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2310 Con_Print("PF_clientcommand: entity is not a client\n");
2314 temp_client = host_client;
2315 host_client = svs.clients + i;
2316 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2317 host_client = temp_client;
2320 //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)
2321 static void VM_SV_setattachment (void)
2323 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2324 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2325 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2328 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2330 if (e == prog->edicts)
2332 VM_Warning("setattachment: can not modify world entity\n");
2335 if (e->priv.server->free)
2337 VM_Warning("setattachment: can not modify free entity\n");
2341 if (tagentity == NULL)
2342 tagentity = prog->edicts;
2346 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2348 model = SV_GetModelFromEdict(tagentity);
2351 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2353 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);
2356 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));
2359 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2360 PRVM_serveredictfloat(e, tag_index) = tagindex;
2363 /////////////////////////////////////////
2364 // DP_MD3_TAGINFO extension coded by VorteX
2366 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2370 i = (int)PRVM_serveredictfloat(e, modelindex);
2371 if (i < 1 || i >= MAX_MODELS)
2374 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2377 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2384 Matrix4x4_CreateIdentity(tag_localmatrix);
2386 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2388 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2399 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2402 float pitchsign = 1;
2404 scale = PRVM_serveredictfloat(ent, scale);
2409 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);
2412 pitchsign = SV_GetPitchSign(ent);
2413 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);
2417 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2420 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2422 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2423 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2424 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2425 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2427 *out = identitymatrix;
2431 // Warnings/errors code:
2432 // 0 - normal (everything all-right)
2435 // 3 - null or non-precached model
2436 // 4 - no tags with requested index
2437 // 5 - runaway loop at attachment chain
2438 extern cvar_t cl_bob;
2439 extern cvar_t cl_bobcycle;
2440 extern cvar_t cl_bobup;
2441 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2444 int modelindex, attachloop;
2445 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2448 *out = identitymatrix; // warnings and errors return identical matrix
2450 if (ent == prog->edicts)
2452 if (ent->priv.server->free)
2455 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2456 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2459 model = SV_GetModelByIndex(modelindex);
2461 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2462 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2463 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2465 tagmatrix = identitymatrix;
2466 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2470 if (attachloop >= 256) // prevent runaway looping
2472 // apply transformation by child's tagindex on parent entity and then
2473 // by parent entity itself
2474 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2475 if (ret && attachloop == 0)
2477 SV_GetEntityMatrix(ent, &entitymatrix, false);
2478 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2479 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2480 // next iteration we process the parent entity
2481 if (PRVM_serveredictedict(ent, tag_entity))
2483 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2484 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2491 // RENDER_VIEWMODEL magic
2492 if (PRVM_serveredictedict(ent, viewmodelforclient))
2494 Matrix4x4_Copy(&tagmatrix, out);
2495 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2497 SV_GetEntityMatrix(ent, &entitymatrix, true);
2498 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2501 // Cl_bob, ported from rendering code
2502 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2505 // LordHavoc: this code is *weird*, but not replacable (I think it
2506 // should be done in QC on the server, but oh well, quake is quake)
2507 // LordHavoc: figured out bobup: the time at which the sin is at 180
2508 // degrees (which allows lengthening or squishing the peak or valley)
2509 cycle = sv.time/cl_bobcycle.value;
2510 cycle -= (int)cycle;
2511 if (cycle < cl_bobup.value)
2512 cycle = sin(M_PI * cycle / cl_bobup.value);
2514 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2515 // bob is proportional to velocity in the xy plane
2516 // (don't count Z, or jumping messes it up)
2517 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;
2518 bob = bob*0.3 + bob*0.7*cycle;
2519 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2526 //float(entity ent, string tagname) gettagindex;
2528 static void VM_SV_gettagindex (void)
2531 const char *tag_name;
2534 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2536 ent = PRVM_G_EDICT(OFS_PARM0);
2537 tag_name = PRVM_G_STRING(OFS_PARM1);
2539 if (ent == prog->edicts)
2541 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2544 if (ent->priv.server->free)
2546 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2551 if (!SV_GetModelFromEdict(ent))
2552 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2555 tag_index = SV_GetTagIndex(ent, tag_name);
2557 if(developer_extra.integer)
2558 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2560 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2563 //vector(entity ent, float tagindex) gettaginfo;
2564 static void VM_SV_gettaginfo (void)
2568 matrix4x4_t tag_matrix;
2569 matrix4x4_t tag_localmatrix;
2571 const char *tagname;
2573 vec3_t fo, le, up, trans;
2574 const dp_model_t *model;
2576 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2578 e = PRVM_G_EDICT(OFS_PARM0);
2579 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2581 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2582 Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
2583 VectorScale(le, -1, PRVM_serverglobalvector(v_right));
2584 model = SV_GetModelFromEdict(e);
2585 VM_GenerateFrameGroupBlend(e->priv.server->framegroupblend, e);
2586 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
2587 VM_UpdateEdictSkeleton(e, model, e->priv.server->frameblend);
2588 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2589 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2591 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2592 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(tagname) : 0;
2593 VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
2594 VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
2595 VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
2596 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2601 VM_Warning("gettagindex: can't affect world entity\n");
2604 VM_Warning("gettagindex: can't affect free entity\n");
2607 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2610 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2613 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2618 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2619 static void VM_SV_dropclient (void)
2622 client_t *oldhostclient;
2623 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2624 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2625 if (clientnum < 0 || clientnum >= svs.maxclients)
2627 VM_Warning("dropclient: not a client\n");
2630 if (!svs.clients[clientnum].active)
2632 VM_Warning("dropclient: that client slot is not connected\n");
2635 oldhostclient = host_client;
2636 host_client = svs.clients + clientnum;
2637 SV_DropClient(false);
2638 host_client = oldhostclient;
2641 //entity() spawnclient (DP_SV_BOTCLIENT)
2642 static void VM_SV_spawnclient (void)
2646 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2647 prog->xfunction->builtinsprofile += 2;
2649 for (i = 0;i < svs.maxclients;i++)
2651 if (!svs.clients[i].active)
2653 prog->xfunction->builtinsprofile += 100;
2654 SV_ConnectClient (i, NULL);
2655 // this has to be set or else ClientDisconnect won't be called
2656 // we assume the qc will call ClientConnect...
2657 svs.clients[i].clientconnectcalled = true;
2658 ed = PRVM_EDICT_NUM(i + 1);
2662 VM_RETURN_EDICT(ed);
2665 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2666 static void VM_SV_clienttype (void)
2669 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2670 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2671 if (clientnum < 0 || clientnum >= svs.maxclients)
2672 PRVM_G_FLOAT(OFS_RETURN) = 3;
2673 else if (!svs.clients[clientnum].active)
2674 PRVM_G_FLOAT(OFS_RETURN) = 0;
2675 else if (svs.clients[clientnum].netconnection)
2676 PRVM_G_FLOAT(OFS_RETURN) = 1;
2678 PRVM_G_FLOAT(OFS_RETURN) = 2;
2685 string(string key) serverkey
2688 void VM_SV_serverkey(void)
2690 char string[VM_STRINGTEMP_LENGTH];
2691 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2692 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2693 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2696 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2697 static void VM_SV_setmodelindex (void)
2702 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2704 e = PRVM_G_EDICT(OFS_PARM0);
2705 if (e == prog->edicts)
2707 VM_Warning("setmodelindex: can not modify world entity\n");
2710 if (e->priv.server->free)
2712 VM_Warning("setmodelindex: can not modify free entity\n");
2715 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2716 if (i <= 0 || i >= MAX_MODELS)
2718 VM_Warning("setmodelindex: invalid modelindex\n");
2721 if (!sv.model_precache[i][0])
2723 VM_Warning("setmodelindex: model not precached\n");
2727 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
2728 PRVM_serveredictfloat(e, modelindex) = i;
2730 mod = SV_GetModelByIndex(i);
2734 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2735 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2737 SetMinMaxSize (e, quakemins, quakemaxs, true);
2740 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2743 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2744 static void VM_SV_modelnameforindex (void)
2747 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2749 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2751 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2752 if (i <= 0 || i >= MAX_MODELS)
2754 VM_Warning("modelnameforindex: invalid modelindex\n");
2757 if (!sv.model_precache[i][0])
2759 VM_Warning("modelnameforindex: model not precached\n");
2763 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2766 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2767 static void VM_SV_particleeffectnum (void)
2770 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2771 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2774 PRVM_G_FLOAT(OFS_RETURN) = i;
2777 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2778 static void VM_SV_trailparticles (void)
2780 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2782 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2785 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2786 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2787 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2788 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2789 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2790 SV_FlushBroadcastMessages();
2793 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2794 static void VM_SV_pointparticles (void)
2796 int effectnum, count;
2798 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2800 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2803 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2804 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2805 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2806 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2807 if (count == 1 && !VectorLength2(vel))
2810 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2811 MSG_WriteShort(&sv.datagram, effectnum);
2812 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2816 // 1+2+12+12+2=29 bytes
2817 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2818 MSG_WriteShort(&sv.datagram, effectnum);
2819 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2820 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2821 MSG_WriteShort(&sv.datagram, count);
2824 SV_FlushBroadcastMessages();
2827 //PF_setpause, // void(float pause) setpause = #531;
2828 static void VM_SV_setpause(void) {
2830 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2831 if (pauseValue != 0) { //pause the game
2833 sv.pausedstart = Sys_DoubleTime();
2834 } else { //disable pause, in case it was enabled
2835 if (sv.paused != 0) {
2840 // send notification to all clients
2841 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2842 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2845 // #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.
2846 static void VM_SV_skel_create(void)
2848 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2849 dp_model_t *model = SV_GetModelByIndex(modelindex);
2850 skeleton_t *skeleton;
2852 PRVM_G_FLOAT(OFS_RETURN) = 0;
2853 if (!model || !model->num_bones)
2855 for (i = 0;i < MAX_EDICTS;i++)
2856 if (!prog->skeletons[i])
2858 if (i == MAX_EDICTS)
2860 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2861 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2862 skeleton->model = model;
2863 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2864 // initialize to identity matrices
2865 for (i = 0;i < skeleton->model->num_bones;i++)
2866 skeleton->relativetransforms[i] = identitymatrix;
2869 // #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
2870 static void VM_SV_skel_build(void)
2872 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2873 skeleton_t *skeleton;
2874 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2875 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2876 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2877 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2878 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2879 dp_model_t *model = SV_GetModelByIndex(modelindex);
2884 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2885 frameblend_t frameblend[MAX_FRAMEBLENDS];
2886 matrix4x4_t blendedmatrix;
2888 PRVM_G_FLOAT(OFS_RETURN) = 0;
2889 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2891 firstbone = max(0, firstbone);
2892 lastbone = min(lastbone, model->num_bones - 1);
2893 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2894 VM_GenerateFrameGroupBlend(framegroupblend, ed);
2895 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
2896 blendfrac = 1.0f - retainfrac;
2897 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2898 frameblend[numblends].lerp *= blendfrac;
2899 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2901 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2902 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2903 for (blendindex = 0;blendindex < numblends;blendindex++)
2905 Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2906 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2908 skeleton->relativetransforms[bonenum] = blendedmatrix;
2910 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2913 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2914 static void VM_SV_skel_get_numbones(void)
2916 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2917 skeleton_t *skeleton;
2918 PRVM_G_FLOAT(OFS_RETURN) = 0;
2919 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2921 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2924 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2925 static void VM_SV_skel_get_bonename(void)
2927 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2928 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2929 skeleton_t *skeleton;
2930 PRVM_G_INT(OFS_RETURN) = 0;
2931 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2933 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2935 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(skeleton->model->data_bones[bonenum].name);
2938 // #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)
2939 static void VM_SV_skel_get_boneparent(void)
2941 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2942 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2943 skeleton_t *skeleton;
2944 PRVM_G_FLOAT(OFS_RETURN) = 0;
2945 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2947 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2949 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2952 // #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
2953 static void VM_SV_skel_find_bone(void)
2955 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2956 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2957 skeleton_t *skeleton;
2958 PRVM_G_FLOAT(OFS_RETURN) = 0;
2959 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2961 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2964 // #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)
2965 static void VM_SV_skel_get_bonerel(void)
2967 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2968 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2969 skeleton_t *skeleton;
2971 vec3_t forward, left, up, origin;
2972 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2973 VectorClear(PRVM_clientglobalvector(v_forward));
2974 VectorClear(PRVM_clientglobalvector(v_right));
2975 VectorClear(PRVM_clientglobalvector(v_up));
2976 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2978 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2980 matrix = skeleton->relativetransforms[bonenum];
2981 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2982 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2983 VectorNegate(left, PRVM_clientglobalvector(v_right));
2984 VectorCopy(up, PRVM_clientglobalvector(v_up));
2985 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2988 // #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)
2989 static void VM_SV_skel_get_boneabs(void)
2991 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2992 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2993 skeleton_t *skeleton;
2996 vec3_t forward, left, up, origin;
2997 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2998 VectorClear(PRVM_clientglobalvector(v_forward));
2999 VectorClear(PRVM_clientglobalvector(v_right));
3000 VectorClear(PRVM_clientglobalvector(v_up));
3001 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3003 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3005 matrix = skeleton->relativetransforms[bonenum];
3006 // convert to absolute
3007 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3010 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3012 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3013 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3014 VectorNegate(left, PRVM_clientglobalvector(v_right));
3015 VectorCopy(up, PRVM_clientglobalvector(v_up));
3016 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3019 // #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)
3020 static void VM_SV_skel_set_bone(void)
3022 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3023 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3024 vec3_t forward, left, up, origin;
3025 skeleton_t *skeleton;
3027 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3029 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3031 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3032 VectorNegate(PRVM_clientglobalvector(v_right), left);
3033 VectorCopy(PRVM_clientglobalvector(v_up), up);
3034 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3035 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3036 skeleton->relativetransforms[bonenum] = matrix;
3039 // #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)
3040 static void VM_SV_skel_mul_bone(void)
3042 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3043 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3044 vec3_t forward, left, up, origin;
3045 skeleton_t *skeleton;
3048 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3050 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3052 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3053 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3054 VectorNegate(PRVM_clientglobalvector(v_right), left);
3055 VectorCopy(PRVM_clientglobalvector(v_up), up);
3056 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3057 temp = skeleton->relativetransforms[bonenum];
3058 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3061 // #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)
3062 static void VM_SV_skel_mul_bones(void)
3064 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3065 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3066 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3068 vec3_t forward, left, up, origin;
3069 skeleton_t *skeleton;
3072 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3074 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3075 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3076 VectorNegate(PRVM_clientglobalvector(v_right), left);
3077 VectorCopy(PRVM_clientglobalvector(v_up), up);
3078 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3079 firstbone = max(0, firstbone);
3080 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3081 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3083 temp = skeleton->relativetransforms[bonenum];
3084 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3088 // #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
3089 static void VM_SV_skel_copybones(void)
3091 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3092 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3093 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3094 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3096 skeleton_t *skeletondst;
3097 skeleton_t *skeletonsrc;
3098 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3100 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3102 firstbone = max(0, firstbone);
3103 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3104 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3105 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3106 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3109 // #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)
3110 static void VM_SV_skel_delete(void)
3112 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3113 skeleton_t *skeleton;
3114 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3117 prog->skeletons[skeletonindex] = NULL;
3120 // #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
3121 static void VM_SV_frameforname(void)
3123 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3124 dp_model_t *model = SV_GetModelByIndex(modelindex);
3125 const char *name = PRVM_G_STRING(OFS_PARM1);
3127 PRVM_G_FLOAT(OFS_RETURN) = -1;
3128 if (!model || !model->animscenes)
3130 for (i = 0;i < model->numframes;i++)
3132 if (!strcasecmp(model->animscenes[i].name, name))
3134 PRVM_G_FLOAT(OFS_RETURN) = i;
3140 // #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.
3141 static void VM_SV_frameduration(void)
3143 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3144 dp_model_t *model = SV_GetModelByIndex(modelindex);
3145 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3146 PRVM_G_FLOAT(OFS_RETURN) = 0;
3147 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3149 if (model->animscenes[framenum].framerate)
3150 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3154 prvm_builtin_t vm_sv_builtins[] = {
3155 NULL, // #0 NULL function (not callable) (QUAKE)
3156 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3157 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3158 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3159 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3160 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3161 VM_break, // #6 void() break (QUAKE)
3162 VM_random, // #7 float() random (QUAKE)
3163 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3164 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3165 VM_error, // #10 void(string e) error (QUAKE)
3166 VM_objerror, // #11 void(string e) objerror (QUAKE)
3167 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3168 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3169 VM_spawn, // #14 entity() spawn (QUAKE)
3170 VM_remove, // #15 void(entity e) remove (QUAKE)
3171 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3172 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3173 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3174 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3175 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3176 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3177 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3178 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3179 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3180 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3181 VM_ftos, // #26 string(float f) ftos (QUAKE)
3182 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3183 VM_coredump, // #28 void() coredump (QUAKE)
3184 VM_traceon, // #29 void() traceon (QUAKE)
3185 VM_traceoff, // #30 void() traceoff (QUAKE)
3186 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3187 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3188 NULL, // #33 (QUAKE)
3189 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3190 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3191 VM_rint, // #36 float(float v) rint (QUAKE)
3192 VM_floor, // #37 float(float v) floor (QUAKE)
3193 VM_ceil, // #38 float(float v) ceil (QUAKE)
3194 NULL, // #39 (QUAKE)
3195 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3196 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3197 NULL, // #42 (QUAKE)
3198 VM_fabs, // #43 float(float f) fabs (QUAKE)
3199 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3200 VM_cvar, // #45 float(string s) cvar (QUAKE)
3201 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3202 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3203 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3204 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3205 NULL, // #50 (QUAKE)
3206 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3207 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3208 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3209 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3210 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3211 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3212 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3213 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3214 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3215 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3216 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3217 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3218 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3219 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3220 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3221 NULL, // #66 (QUAKE)
3222 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3223 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3224 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3225 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3226 NULL, // #71 (QUAKE)
3227 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3228 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3229 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3230 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3231 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3232 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3233 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3234 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3235 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3236 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3237 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3238 NULL, // #83 (QUAKE)
3239 NULL, // #84 (QUAKE)
3240 NULL, // #85 (QUAKE)
3241 NULL, // #86 (QUAKE)
3242 NULL, // #87 (QUAKE)
3243 NULL, // #88 (QUAKE)
3244 NULL, // #89 (QUAKE)
3245 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3246 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3247 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3248 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3249 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3250 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3251 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3252 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3253 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3254 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3255 // FrikaC and Telejano range #100-#199
3266 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3267 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3268 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3269 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3270 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3271 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3272 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3273 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3274 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3275 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3356 // FTEQW range #200-#299
3375 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3378 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3379 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3380 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3381 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3382 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3383 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3384 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3385 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3386 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3387 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3389 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3397 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3420 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.
3421 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
3422 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3423 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3424 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)
3425 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
3426 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)
3427 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)
3428 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)
3429 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)
3430 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)
3431 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
3432 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)
3433 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
3434 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.
3457 // CSQC range #300-#399
3458 NULL, // #300 void() clearscene (EXT_CSQC)
3459 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3460 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3461 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3462 NULL, // #304 void() renderscene (EXT_CSQC)
3463 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3464 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3465 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3466 NULL, // #308 void() R_EndPolygon
3468 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3469 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3473 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3474 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3475 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3476 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3477 NULL, // #319 void(string name) freepic (EXT_CSQC)
3478 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3479 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3480 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3481 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3482 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3483 NULL, // #325 void(void) drawresetcliparea
3488 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3489 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3490 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3491 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3492 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3493 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3494 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3495 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3496 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3497 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3498 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3499 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3500 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3501 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3502 NULL, // #344 vector() getmousepos (EXT_CSQC)
3503 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3504 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3505 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3506 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3507 NULL, // #349 float() isdemo (EXT_CSQC)
3508 VM_isserver, // #350 float() isserver (EXT_CSQC)
3509 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3510 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3511 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3512 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3518 NULL, // #360 float() readbyte (EXT_CSQC)
3519 NULL, // #361 float() readchar (EXT_CSQC)
3520 NULL, // #362 float() readshort (EXT_CSQC)
3521 NULL, // #363 float() readlong (EXT_CSQC)
3522 NULL, // #364 float() readcoord (EXT_CSQC)
3523 NULL, // #365 float() readangle (EXT_CSQC)
3524 NULL, // #366 string() readstring (EXT_CSQC)
3525 NULL, // #367 float() readfloat (EXT_CSQC)
3558 // LordHavoc's range #400-#499
3559 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3560 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3561 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3562 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3563 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3564 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3565 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3566 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3567 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)
3568 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3569 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3570 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3571 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3572 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3573 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3574 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3575 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3576 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3577 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3578 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3579 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3580 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3581 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3582 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3583 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3584 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3585 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3586 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3587 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3588 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3589 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3590 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3591 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3592 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3593 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3594 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3595 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3596 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3597 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3598 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3599 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3600 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3601 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3602 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3603 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3604 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3605 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3606 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3607 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3608 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3609 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3610 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3611 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3612 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3613 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3614 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3615 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3616 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3618 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3619 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3620 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3621 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3622 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3623 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3624 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3625 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3626 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3627 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3628 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3630 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3631 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3632 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3633 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3634 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3635 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3636 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3637 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3638 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3639 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3640 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3641 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3642 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3643 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3644 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3645 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3653 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3654 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3655 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3656 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3657 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3658 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3659 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3660 VM_SV_WritePicture, // #501
3662 VM_whichpack, // #503 string(string) whichpack = #503;
3669 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3670 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3671 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3672 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)
3673 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3674 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3675 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3676 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3677 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3678 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3688 VM_loadfromdata, // #529
3689 VM_loadfromfile, // #530
3690 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3692 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3693 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3699 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3700 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3701 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3764 VM_callfunction, // #605
3765 VM_writetofile, // #606
3766 VM_isfunction, // #607
3772 VM_parseentitydata, // #613
3783 VM_SV_getextresponse, // #624 string getextresponse(void)
3786 VM_sprintf, // #627 string sprintf(string format, ...)
3787 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3788 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3792 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3794 void VM_SV_Cmd_Init(void)
3799 void VM_SV_Cmd_Reset(void)
3801 World_End(&sv.world);
3802 if(PRVM_serverfunction(SV_Shutdown))
3804 func_t s = PRVM_serverfunction(SV_Shutdown);
3805 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3806 PRVM_ExecuteProgram(s,"SV_Shutdown() required");