6 //============================================================================
11 const char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
24 "DP_CSQC_ENTITYWORLDOBJECT "
25 "DP_CSQC_ENTITYMODELLIGHT "
26 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
27 "DP_CSQC_MULTIFRAME_INTERPOLATION "
28 "DP_CSQC_BOXPARTICLES "
29 "DP_CSQC_SPAWNPARTICLE "
30 "DP_CSQC_QUERYRENDERENTITY "
31 "DP_CSQC_ROTATEMOVES "
44 "DP_EF_RESTARTANIM_BIT "
49 "DP_ENT_CUSTOMCOLORMAP "
50 "DP_ENT_EXTERIORMODELTOCLIENT "
53 "DP_ENT_LOWPRECISION "
55 "DP_ENT_TRAILEFFECTNUM "
57 "DP_GFX_EXTERNALTEXTURES "
58 "DP_GFX_EXTERNALTEXTURES_PERMAP "
60 "DP_GFX_MODEL_INTERPOLATION "
61 "DP_GFX_QUAKE3MODELTAGS "
65 "DP_GFX_FONTS_FREETYPE "
67 "DP_FONT_VARIABLEWIDTH "
69 "DP_HALFLIFE_MAP_CVAR "
72 "DP_LIGHTSTYLE_STATICVALUE "
76 "DP_MOVETYPEBOUNCEMISSILE "
77 "DP_MOVETYPEFLYWORLDONLY "
80 "DP_QC_ASINACOSATANATAN2TAN "
86 "DP_QC_CVAR_DEFSTRING "
87 "DP_QC_CVAR_DESCRIPTION "
91 "DP_QC_DIGEST_SHA256 "
96 "DP_QC_EXTRESPONSEPACKET "
98 "DP_QC_FINDCHAINFLAGS "
99 "DP_QC_FINDCHAINFLOAT "
100 "DP_QC_FINDCHAIN_TOFIELD "
106 "DP_QC_GETSURFACETRIANGLE "
107 "DP_QC_GETSURFACEPOINTATTRIBUTE "
109 "DP_QC_GETTAGINFO_BONEPROPERTIES "
111 "DP_QC_GETTIME_CDTRACK "
115 "DP_QC_MULTIPLETEMPSTRINGS "
116 "DP_QC_NUM_FOR_EDICT "
118 "DP_QC_SINCOSSQRTPOW "
121 "DP_QC_STRINGBUFFERS "
122 "DP_QC_STRINGBUFFERS_CVARLIST "
123 "DP_QC_STRINGCOLORFUNCTIONS "
124 "DP_QC_STRING_CASE_FUNCTIONS "
126 "DP_QC_TOKENIZEBYSEPARATOR "
127 "DP_QC_TOKENIZE_CONSOLE "
130 "DP_QC_TRACE_MOVETYPE_HITMODEL "
131 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
132 "DP_QC_UNLIMITEDTEMPSTRINGS "
136 "DP_QC_VECTOANGLES_WITH_ROLL "
137 "DP_QC_VECTORVECTORS "
144 "DP_SKELETONOBJECTS "
145 "DP_SND_DIRECTIONLESSATTNNONE "
147 "DP_SND_SOUND7_WIP1 "
148 "DP_SND_SOUND7_WIP2 "
152 "DP_SND_GETSOUNDTIME "
154 "DP_VIDEO_SUBTITLES "
158 "DP_SV_BOUNCEFACTOR "
159 "DP_SV_CLIENTCAMERA "
160 "DP_SV_CLIENTCOLORS "
163 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
164 "DP_SV_DISCARDABLEDEMO "
165 "DP_SV_DRAWONLYTOCLIENT "
168 "DP_SV_ENTITYCONTENTSTRANSITION "
169 "DP_SV_MODELFLAGS_AS_EFFECTS "
170 "DP_SV_MOVETYPESTEP_LANDEVENT "
172 "DP_SV_NODRAWTOCLIENT "
173 "DP_SV_ONENTITYNOSPAWNFUNCTION "
174 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
176 "DP_SV_PING_PACKETLOSS "
177 "DP_SV_PLAYERPHYSICS "
179 "DP_SV_POINTPARTICLES "
181 "DP_SV_PRECACHEANYTIME "
185 "DP_SV_ROTATINGBMODEL "
189 "DP_SV_SPAWNFUNC_PREFIX "
190 "DP_SV_WRITEPICTURE "
191 "DP_SV_WRITEUNTERMINATEDSTRING "
195 "DP_TE_EXPLOSIONRGB "
197 "DP_TE_PARTICLECUBE "
198 "DP_TE_PARTICLERAIN "
199 "DP_TE_PARTICLESNOW "
201 "DP_TE_QUADEFFECTS1 "
204 "DP_TE_STANDARDEFFECTBUILTINS "
205 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
209 "FTE_CSQC_SKELETONOBJECTS "
212 "KRIMZON_SV_PARSECLIENTCOMMAND "
215 "NEXUIZ_PLAYERMODEL "
217 "PRYDON_CLIENTCURSOR "
218 "TENEBRAE_GFX_DLIGHTS "
221 //"EXT_CSQC " // not ready yet
228 This is the only valid way to move an object without using the physics of the world (setting velocity and waiting). Directly changing origin will not set internal links correctly, so clipping would be messed up. This should be called when an object is spawned, and then only if it is teleported.
230 setorigin (entity, origin)
233 static void VM_SV_setorigin (void)
238 VM_SAFEPARMCOUNT(2, VM_setorigin);
240 e = PRVM_G_EDICT(OFS_PARM0);
241 if (e == prog->edicts)
243 VM_Warning("setorigin: can not modify world entity\n");
246 if (e->priv.server->free)
248 VM_Warning("setorigin: can not modify free entity\n");
251 org = PRVM_G_VECTOR(OFS_PARM1);
252 VectorCopy (org, PRVM_serveredictvector(e, origin));
256 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
257 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
261 for (i=0 ; i<3 ; i++)
263 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
265 // set derived values
266 VectorCopy (min, PRVM_serveredictvector(e, mins));
267 VectorCopy (max, PRVM_serveredictvector(e, maxs));
268 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
277 the size box is rotated by the current angle
278 LordHavoc: no it isn't...
280 setsize (entity, minvector, maxvector)
283 static void VM_SV_setsize (void)
288 VM_SAFEPARMCOUNT(3, VM_setsize);
290 e = PRVM_G_EDICT(OFS_PARM0);
291 if (e == prog->edicts)
293 VM_Warning("setsize: can not modify world entity\n");
296 if (e->priv.server->free)
298 VM_Warning("setsize: can not modify free entity\n");
301 min = PRVM_G_VECTOR(OFS_PARM1);
302 max = PRVM_G_VECTOR(OFS_PARM2);
303 SetMinMaxSize (e, min, max, false);
311 setmodel(entity, model)
314 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
315 static void VM_SV_setmodel (void)
321 VM_SAFEPARMCOUNT(2, VM_setmodel);
323 e = PRVM_G_EDICT(OFS_PARM0);
324 if (e == prog->edicts)
326 VM_Warning("setmodel: can not modify world entity\n");
329 if (e->priv.server->free)
331 VM_Warning("setmodel: can not modify free entity\n");
334 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
335 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
336 PRVM_serveredictfloat(e, modelindex) = i;
338 mod = SV_GetModelByIndex(i);
342 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
343 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
345 SetMinMaxSize (e, quakemins, quakemaxs, true);
348 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
355 single print to a specific client
357 sprint(clientent, value)
360 static void VM_SV_sprint (void)
364 char string[VM_STRINGTEMP_LENGTH];
366 VM_VarString(1, string, sizeof(string));
368 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
370 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
371 // LordHavoc: div0 requested that sprintto world operate like print
378 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
380 VM_Warning("tried to centerprint to a non-client\n");
384 client = svs.clients + entnum-1;
385 if (!client->netconnection)
388 MSG_WriteChar(&client->netconnection->message,svc_print);
389 MSG_WriteString(&client->netconnection->message, string);
397 single print to a specific client
399 centerprint(clientent, value)
402 static void VM_SV_centerprint (void)
406 char string[VM_STRINGTEMP_LENGTH];
408 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
410 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
412 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
414 VM_Warning("tried to centerprint to a non-client\n");
418 client = svs.clients + entnum-1;
419 if (!client->netconnection)
422 VM_VarString(1, string, sizeof(string));
423 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
424 MSG_WriteString(&client->netconnection->message, string);
431 particle(origin, color, count)
434 static void VM_SV_particle (void)
440 VM_SAFEPARMCOUNT(4, VM_SV_particle);
442 org = PRVM_G_VECTOR(OFS_PARM0);
443 dir = PRVM_G_VECTOR(OFS_PARM1);
444 color = PRVM_G_FLOAT(OFS_PARM2);
445 count = PRVM_G_FLOAT(OFS_PARM3);
446 SV_StartParticle (org, dir, (int)color, (int)count);
456 static void VM_SV_ambientsound (void)
460 float vol, attenuation;
463 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
465 pos = PRVM_G_VECTOR (OFS_PARM0);
466 samp = PRVM_G_STRING(OFS_PARM1);
467 vol = PRVM_G_FLOAT(OFS_PARM2);
468 attenuation = PRVM_G_FLOAT(OFS_PARM3);
470 // check to see if samp was properly precached
471 soundnum = SV_SoundIndex(samp, 1);
479 // add an svc_spawnambient command to the level signon packet
482 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
484 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
486 MSG_WriteVector(&sv.signon, pos, sv.protocol);
488 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
489 MSG_WriteShort (&sv.signon, soundnum);
491 MSG_WriteByte (&sv.signon, soundnum);
493 MSG_WriteByte (&sv.signon, (int)(vol*255));
494 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
502 Each entity can have eight independant sound sources, like voice,
505 Channel 0 is an auto-allocate channel, the others override anything
506 already running on that entity/channel pair.
508 An attenuation of 0 will play full volume everywhere in the level.
509 Larger attenuations will drop off.
513 static void VM_SV_sound (void)
517 prvm_edict_t *entity;
523 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
525 entity = PRVM_G_EDICT(OFS_PARM0);
526 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
527 sample = PRVM_G_STRING(OFS_PARM2);
528 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
531 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
535 attenuation = PRVM_G_FLOAT(OFS_PARM4);
539 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
544 if(channel >= 8 && channel <= 15) // weird QW feature
546 flags |= CHANFLAG_RELIABLE;
551 flags = PRVM_G_FLOAT(OFS_PARM6);
553 if (volume < 0 || volume > 255)
555 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
559 if (attenuation < 0 || attenuation > 4)
561 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
565 channel = CHAN_USER2ENGINE(channel);
567 if (!IS_CHAN(channel))
569 VM_Warning("SV_StartSound: channel must be in range 0-127\n");
573 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE, pitchchange);
580 Follows the same logic as VM_SV_sound, except instead of
581 an entity, an origin for the sound is provided, and channel
582 is omitted (since no entity is being tracked).
586 static void VM_SV_pointsound(void)
594 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
596 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
597 sample = PRVM_G_STRING(OFS_PARM1);
598 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
599 attenuation = PRVM_G_FLOAT(OFS_PARM3);
600 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
602 if (volume < 0 || volume > 255)
604 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
608 if (attenuation < 0 || attenuation > 4)
610 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
614 SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
621 Used for use tracing and shot targeting
622 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
623 if the tryents flag is set.
625 traceline (vector1, vector2, movetype, ignore)
628 static void VM_SV_traceline (void)
635 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
637 prog->xfunction->builtinsprofile += 30;
639 v1 = PRVM_G_VECTOR(OFS_PARM0);
640 v2 = PRVM_G_VECTOR(OFS_PARM1);
641 move = (int)PRVM_G_FLOAT(OFS_PARM2);
642 ent = PRVM_G_EDICT(OFS_PARM3);
644 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]))
645 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));
647 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
649 VM_SetTraceGlobals(&trace);
657 Used for use tracing and shot targeting
658 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
659 if the tryents flag is set.
661 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
664 // LordHavoc: added this for my own use, VERY useful, similar to traceline
665 static void VM_SV_tracebox (void)
667 float *v1, *v2, *m1, *m2;
672 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
674 prog->xfunction->builtinsprofile += 30;
676 v1 = PRVM_G_VECTOR(OFS_PARM0);
677 m1 = PRVM_G_VECTOR(OFS_PARM1);
678 m2 = PRVM_G_VECTOR(OFS_PARM2);
679 v2 = PRVM_G_VECTOR(OFS_PARM3);
680 move = (int)PRVM_G_FLOAT(OFS_PARM4);
681 ent = PRVM_G_EDICT(OFS_PARM5);
683 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]))
684 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));
686 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
688 VM_SetTraceGlobals(&trace);
691 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
696 vec3_t original_origin;
697 vec3_t original_velocity;
698 vec3_t original_angles;
699 vec3_t original_avelocity;
702 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
703 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
704 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
705 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
707 gravity = PRVM_serveredictfloat(tossent, gravity);
710 gravity *= sv_gravity.value * 0.025;
712 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
714 SV_CheckVelocity (tossent);
715 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
716 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
717 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
718 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
719 trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
720 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
721 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
723 if (trace.fraction < 1)
727 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
728 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
729 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
730 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
735 static void VM_SV_tracetoss (void)
739 prvm_edict_t *ignore;
741 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
743 prog->xfunction->builtinsprofile += 600;
745 ent = PRVM_G_EDICT(OFS_PARM0);
746 if (ent == prog->edicts)
748 VM_Warning("tracetoss: can not use world entity\n");
751 ignore = PRVM_G_EDICT(OFS_PARM1);
753 trace = SV_Trace_Toss (ent, ignore);
755 VM_SetTraceGlobals(&trace);
758 //============================================================================
760 static int checkpvsbytes;
761 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
763 static int VM_SV_newcheckclient (int check)
769 // cycle to the next one
771 check = bound(1, check, svs.maxclients);
772 if (check == svs.maxclients)
780 prog->xfunction->builtinsprofile++;
782 if (i == svs.maxclients+1)
784 // look up the client's edict
785 ent = PRVM_EDICT_NUM(i);
786 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
787 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
789 // found a valid client (possibly the same one again)
793 // get the PVS for the entity
794 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
796 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
797 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
806 Returns a client (or object that has a client enemy) that would be a
809 If there is more than one valid option, they are cycled each frame
811 If (self.origin + self.viewofs) is not in the PVS of the current target,
812 it is not returned at all.
817 int c_invis, c_notvis;
818 static void VM_SV_checkclient (void)
820 prvm_edict_t *ent, *self;
823 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
825 // find a new check if on a new frame
826 if (sv.time - sv.lastchecktime >= 0.1)
828 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
829 sv.lastchecktime = sv.time;
832 // return check if it might be visible
833 ent = PRVM_EDICT_NUM(sv.lastcheck);
834 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
836 VM_RETURN_EDICT(prog->edicts);
840 // if current entity can't possibly see the check entity, return 0
841 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
842 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
843 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
846 VM_RETURN_EDICT(prog->edicts);
850 // might be able to see it
852 VM_RETURN_EDICT(ent);
855 //============================================================================
861 Checks if an entity is in a point's PVS.
862 Should be fast but can be inexact.
864 float checkpvs(vector viewpos, entity viewee) = #240;
867 static void VM_SV_checkpvs (void)
870 prvm_edict_t *viewee;
875 unsigned char fatpvs[MAX_MAP_LEAFS/8];
878 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
879 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
880 viewee = PRVM_G_EDICT(OFS_PARM1);
882 if(viewee->priv.server->free)
884 VM_Warning("checkpvs: can not check free entity\n");
885 PRVM_G_FLOAT(OFS_RETURN) = 4;
890 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
892 // no PVS support on this worldmodel... darn
893 PRVM_G_FLOAT(OFS_RETURN) = 3;
896 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
899 // viewpos isn't in any PVS... darn
900 PRVM_G_FLOAT(OFS_RETURN) = 2;
903 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
905 // using fat PVS like FTEQW does (slow)
906 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
908 // no PVS support on this worldmodel... darn
909 PRVM_G_FLOAT(OFS_RETURN) = 3;
912 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
915 // viewpos isn't in any PVS... darn
916 PRVM_G_FLOAT(OFS_RETURN) = 2;
919 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
928 Sends text over to the client's execution buffer
930 stuffcmd (clientent, value, ...)
933 static void VM_SV_stuffcmd (void)
937 char string[VM_STRINGTEMP_LENGTH];
939 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
941 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
942 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
944 VM_Warning("Can't stuffcmd to a non-client\n");
948 VM_VarString(1, string, sizeof(string));
951 host_client = svs.clients + entnum-1;
952 Host_ClientCommands ("%s", string);
960 Returns a chain of entities that have origins within a spherical area
962 findradius (origin, radius)
965 static void VM_SV_findradius (void)
967 prvm_edict_t *ent, *chain;
968 vec_t radius, radius2;
969 vec3_t org, eorg, mins, maxs;
972 static prvm_edict_t *touchedicts[MAX_EDICTS];
975 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
978 chainfield = PRVM_G_INT(OFS_PARM2);
980 chainfield = prog->fieldoffsets.chain;
982 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
984 chain = (prvm_edict_t *)prog->edicts;
986 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
987 radius = PRVM_G_FLOAT(OFS_PARM1);
988 radius2 = radius * radius;
990 mins[0] = org[0] - (radius + 1);
991 mins[1] = org[1] - (radius + 1);
992 mins[2] = org[2] - (radius + 1);
993 maxs[0] = org[0] + (radius + 1);
994 maxs[1] = org[1] + (radius + 1);
995 maxs[2] = org[2] + (radius + 1);
996 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
997 if (numtouchedicts > MAX_EDICTS)
999 // this never happens
1000 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1001 numtouchedicts = MAX_EDICTS;
1003 for (i = 0;i < numtouchedicts;i++)
1005 ent = touchedicts[i];
1006 prog->xfunction->builtinsprofile++;
1007 // Quake did not return non-solid entities but darkplaces does
1008 // (note: this is the reason you can't blow up fallen zombies)
1009 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1011 // LordHavoc: compare against bounding box rather than center so it
1012 // doesn't miss large objects, and use DotProduct instead of Length
1013 // for a major speedup
1014 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1015 if (sv_gameplayfix_findradiusdistancetobox.integer)
1017 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1018 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1019 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1022 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1023 if (DotProduct(eorg, eorg) < radius2)
1025 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1030 VM_RETURN_EDICT(chain);
1033 static void VM_SV_precache_sound (void)
1035 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1036 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1039 static void VM_SV_precache_model (void)
1041 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1042 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1043 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1050 float(float yaw, float dist[, settrace]) walkmove
1053 static void VM_SV_walkmove (void)
1062 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1064 // assume failure if it returns early
1065 PRVM_G_FLOAT(OFS_RETURN) = 0;
1067 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1068 if (ent == prog->edicts)
1070 VM_Warning("walkmove: can not modify world entity\n");
1073 if (ent->priv.server->free)
1075 VM_Warning("walkmove: can not modify free entity\n");
1078 yaw = PRVM_G_FLOAT(OFS_PARM0);
1079 dist = PRVM_G_FLOAT(OFS_PARM1);
1080 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1082 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1085 yaw = yaw*M_PI*2 / 360;
1087 move[0] = cos(yaw)*dist;
1088 move[1] = sin(yaw)*dist;
1091 // save program state, because SV_movestep may call other progs
1092 oldf = prog->xfunction;
1093 oldself = PRVM_serverglobaledict(self);
1095 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1098 // restore program state
1099 prog->xfunction = oldf;
1100 PRVM_serverglobaledict(self) = oldself;
1111 static void VM_SV_droptofloor (void)
1117 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1119 // assume failure if it returns early
1120 PRVM_G_FLOAT(OFS_RETURN) = 0;
1122 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1123 if (ent == prog->edicts)
1125 VM_Warning("droptofloor: can not modify world entity\n");
1128 if (ent->priv.server->free)
1130 VM_Warning("droptofloor: can not modify free entity\n");
1134 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1137 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1138 if (sv_gameplayfix_unstickentities.integer)
1139 SV_UnstickEntity(ent);
1141 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1142 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1145 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]);
1146 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1147 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1148 VectorSubtract(trace.endpos, offset, trace.endpos);
1149 if (trace.startsolid)
1151 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]);
1152 if (sv_gameplayfix_unstickentities.integer)
1153 SV_UnstickEntity(ent);
1155 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1156 PRVM_serveredictedict(ent, groundentity) = 0;
1157 PRVM_G_FLOAT(OFS_RETURN) = 1;
1159 else if (trace.fraction < 1)
1161 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]);
1162 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1163 if (sv_gameplayfix_unstickentities.integer)
1164 SV_UnstickEntity(ent);
1166 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1167 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1168 PRVM_G_FLOAT(OFS_RETURN) = 1;
1169 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1170 ent->priv.server->suspendedinairflag = true;
1175 if (trace.fraction != 1)
1177 if (trace.fraction < 1)
1178 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1180 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1181 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1182 PRVM_G_FLOAT(OFS_RETURN) = 1;
1183 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1184 ent->priv.server->suspendedinairflag = true;
1193 void(float style, string value) lightstyle
1196 static void VM_SV_lightstyle (void)
1203 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1205 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1206 val = PRVM_G_STRING(OFS_PARM1);
1208 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1209 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1212 // change the string in sv
1213 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1215 // send message to all clients on this server
1216 if (sv.state != ss_active)
1219 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1221 if (client->active && client->netconnection)
1223 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1224 MSG_WriteChar (&client->netconnection->message,style);
1225 MSG_WriteString (&client->netconnection->message, val);
1235 static void VM_SV_checkbottom (void)
1237 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1238 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1246 static void VM_SV_pointcontents (void)
1248 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1249 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1256 Pick a vector for the player to shoot along
1257 vector aim(entity, missilespeed)
1260 static void VM_SV_aim (void)
1262 prvm_edict_t *ent, *check, *bestent;
1263 vec3_t start, dir, end, bestdir;
1266 float dist, bestdist;
1269 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1271 // assume failure if it returns early
1272 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1273 // if sv_aim is so high it can't possibly accept anything, skip out early
1274 if (sv_aim.value >= 1)
1277 ent = PRVM_G_EDICT(OFS_PARM0);
1278 if (ent == prog->edicts)
1280 VM_Warning("aim: can not use world entity\n");
1283 if (ent->priv.server->free)
1285 VM_Warning("aim: can not use free entity\n");
1288 //speed = PRVM_G_FLOAT(OFS_PARM1);
1290 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1293 // try sending a trace straight
1294 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1295 VectorMA (start, 2048, dir, end);
1296 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1297 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1298 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1300 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1305 // try all possible entities
1306 VectorCopy (dir, bestdir);
1307 bestdist = sv_aim.value;
1310 check = PRVM_NEXT_EDICT(prog->edicts);
1311 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1313 prog->xfunction->builtinsprofile++;
1314 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1318 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1319 continue; // don't aim at teammate
1320 for (j=0 ; j<3 ; j++)
1321 end[j] = PRVM_serveredictvector(check, origin)[j]
1322 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1323 VectorSubtract (end, start, dir);
1324 VectorNormalize (dir);
1325 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1326 if (dist < bestdist)
1327 continue; // to far to turn
1328 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1329 if (tr.ent == check)
1330 { // can shoot at this one
1338 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1339 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1340 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1342 VectorNormalize (end);
1343 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1347 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1352 ===============================================================================
1356 ===============================================================================
1359 #define MSG_BROADCAST 0 // unreliable to all
1360 #define MSG_ONE 1 // reliable to one (msg_entity)
1361 #define MSG_ALL 2 // reliable to all
1362 #define MSG_INIT 3 // write to the init string
1363 #define MSG_ENTITY 5
1365 sizebuf_t *WriteDest (void)
1371 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1375 return &sv.datagram;
1378 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1379 entnum = PRVM_NUM_FOR_EDICT(ent);
1380 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1382 VM_Warning ("WriteDest: tried to write to non-client\n");
1383 return &sv.reliable_datagram;
1386 return &svs.clients[entnum-1].netconnection->message;
1389 VM_Warning ("WriteDest: bad destination\n");
1391 return &sv.reliable_datagram;
1397 return sv.writeentitiestoclient_msg;
1403 static void VM_SV_WriteByte (void)
1405 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1406 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1409 static void VM_SV_WriteChar (void)
1411 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1412 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1415 static void VM_SV_WriteShort (void)
1417 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1418 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1421 static void VM_SV_WriteLong (void)
1423 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1424 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1427 static void VM_SV_WriteAngle (void)
1429 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1430 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1433 static void VM_SV_WriteCoord (void)
1435 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1436 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1439 static void VM_SV_WriteString (void)
1441 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1442 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1445 static void VM_SV_WriteUnterminatedString (void)
1447 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1448 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1452 static void VM_SV_WriteEntity (void)
1454 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1455 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1458 // writes a picture as at most size bytes of data
1460 // IMGNAME \0 SIZE(short) IMGDATA
1461 // if failed to read/compress:
1463 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1464 static void VM_SV_WritePicture (void)
1466 const char *imgname;
1470 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1472 imgname = PRVM_G_STRING(OFS_PARM1);
1473 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1477 MSG_WriteString(WriteDest(), imgname);
1478 if(Image_Compress(imgname, size, &buf, &size))
1481 MSG_WriteShort(WriteDest(), size);
1482 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1487 MSG_WriteShort(WriteDest(), 0);
1491 //////////////////////////////////////////////////////////
1493 static void VM_SV_makestatic (void)
1498 // allow 0 parameters due to an id1 qc bug in which this function is used
1499 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1500 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1502 if (prog->argc >= 1)
1503 ent = PRVM_G_EDICT(OFS_PARM0);
1505 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1506 if (ent == prog->edicts)
1508 VM_Warning("makestatic: can not modify world entity\n");
1511 if (ent->priv.server->free)
1513 VM_Warning("makestatic: can not modify free entity\n");
1518 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1523 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1524 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1525 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1527 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1529 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1530 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1531 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1535 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1536 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1537 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1540 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1541 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1542 for (i=0 ; i<3 ; i++)
1544 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1545 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1548 // throw the entity away now
1552 //=============================================================================
1559 static void VM_SV_setspawnparms (void)
1565 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1567 ent = PRVM_G_EDICT(OFS_PARM0);
1568 i = PRVM_NUM_FOR_EDICT(ent);
1569 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1571 Con_Print("tried to setspawnparms on a non-client\n");
1575 // copy spawn parms out of the client_t
1576 client = svs.clients + i-1;
1577 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1578 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1585 Returns a color vector indicating the lighting at the requested point.
1587 (Internal Operation note: actually measures the light beneath the point, just like
1588 the model lighting on the client)
1593 static void VM_SV_getlight (void)
1595 vec3_t ambientcolor, diffusecolor, diffusenormal;
1597 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1598 p = PRVM_G_VECTOR(OFS_PARM0);
1599 VectorClear(ambientcolor);
1600 VectorClear(diffusecolor);
1601 VectorClear(diffusenormal);
1602 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1603 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1604 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1609 unsigned char type; // 1/2/8 or other value if isn't used
1613 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1614 static int vm_customstats_last;
1616 void VM_CustomStats_Clear (void)
1620 Z_Free(vm_customstats);
1621 vm_customstats = NULL;
1622 vm_customstats_last = -1;
1626 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1634 for(i=0; i<vm_customstats_last+1 ;i++)
1636 if(!vm_customstats[i].type)
1638 switch(vm_customstats[i].type)
1640 //string as 16 bytes
1643 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1644 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1645 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1646 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1647 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1649 //float field sent as-is
1651 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1653 //integer value of float field
1655 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1663 // void(float index, float type, .void field) SV_AddStat = #232;
1664 // Set up an auto-sent player stat.
1665 // Client's get thier own fields sent to them. Index may not be less than 32.
1666 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1667 // 1: string (4 stats carrying a total of 16 charactures)
1668 // 2: float (one stat, float converted to an integer for transportation)
1669 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1670 static void VM_SV_AddStat (void)
1675 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1679 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1682 VM_Warning("PF_SV_AddStat: not enough memory\n");
1686 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1687 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1688 off = PRVM_G_INT (OFS_PARM2);
1693 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1696 if(i >= (MAX_CL_STATS-32))
1698 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1701 if(i > (MAX_CL_STATS-32-4) && type == 1)
1703 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1706 vm_customstats[i].type = type;
1707 vm_customstats[i].fieldoffset = off;
1708 if(vm_customstats_last < i)
1709 vm_customstats_last = i;
1716 copies data from one entity to another
1718 copyentity(src, dst)
1721 static void VM_SV_copyentity (void)
1723 prvm_edict_t *in, *out;
1724 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1725 in = PRVM_G_EDICT(OFS_PARM0);
1726 if (in == prog->edicts)
1728 VM_Warning("copyentity: can not read world entity\n");
1731 if (in->priv.server->free)
1733 VM_Warning("copyentity: can not read free entity\n");
1736 out = PRVM_G_EDICT(OFS_PARM1);
1737 if (out == prog->edicts)
1739 VM_Warning("copyentity: can not modify world entity\n");
1742 if (out->priv.server->free)
1744 VM_Warning("copyentity: can not modify free entity\n");
1747 memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
1756 sets the color of a client and broadcasts the update to all connected clients
1758 setcolor(clientent, value)
1761 static void VM_SV_setcolor (void)
1766 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1767 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1768 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1770 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1772 Con_Print("tried to setcolor a non-client\n");
1776 client = svs.clients + entnum-1;
1779 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1780 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1783 if (client->old_colors != client->colors)
1785 client->old_colors = client->colors;
1786 // send notification to all clients
1787 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1788 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1789 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1797 effect(origin, modelname, startframe, framecount, framerate)
1800 static void VM_SV_effect (void)
1804 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1805 s = PRVM_G_STRING(OFS_PARM1);
1808 VM_Warning("effect: no model specified\n");
1812 i = SV_ModelIndex(s, 1);
1815 VM_Warning("effect: model not precached\n");
1819 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1821 VM_Warning("effect: framecount < 1\n");
1825 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1827 VM_Warning("effect: framerate < 1\n");
1831 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));
1834 static void VM_SV_te_blood (void)
1836 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1837 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1839 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1840 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1842 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1843 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1844 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1846 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1847 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1848 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1850 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1851 SV_FlushBroadcastMessages();
1854 static void VM_SV_te_bloodshower (void)
1856 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1857 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1859 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1860 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1862 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1863 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1864 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1866 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1868 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1870 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1872 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1873 SV_FlushBroadcastMessages();
1876 static void VM_SV_te_explosionrgb (void)
1878 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1879 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1880 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1882 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1883 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1884 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1886 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1887 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1888 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1889 SV_FlushBroadcastMessages();
1892 static void VM_SV_te_particlecube (void)
1894 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1895 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1897 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1898 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1900 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1912 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1914 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1915 // gravity true/false
1916 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1918 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1919 SV_FlushBroadcastMessages();
1922 static void VM_SV_te_particlerain (void)
1924 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1925 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1927 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1928 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1934 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1936 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1942 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1944 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1945 SV_FlushBroadcastMessages();
1948 static void VM_SV_te_particlesnow (void)
1950 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1951 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1953 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1954 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1964 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1965 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1968 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1970 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1971 SV_FlushBroadcastMessages();
1974 static void VM_SV_te_spark (void)
1976 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1977 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1979 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1980 MSG_WriteByte(&sv.datagram, TE_SPARK);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1983 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1984 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1986 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1987 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1988 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1990 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1991 SV_FlushBroadcastMessages();
1994 static void VM_SV_te_gunshotquad (void)
1996 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1997 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1998 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2000 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2001 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2002 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2003 SV_FlushBroadcastMessages();
2006 static void VM_SV_te_spikequad (void)
2008 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2009 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2010 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2012 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2014 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2015 SV_FlushBroadcastMessages();
2018 static void VM_SV_te_superspikequad (void)
2020 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2021 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2022 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2024 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2025 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2026 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2027 SV_FlushBroadcastMessages();
2030 static void VM_SV_te_explosionquad (void)
2032 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2033 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2034 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2036 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2037 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2038 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2039 SV_FlushBroadcastMessages();
2042 static void VM_SV_te_smallflash (void)
2044 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2045 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2046 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2048 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2049 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2050 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2051 SV_FlushBroadcastMessages();
2054 static void VM_SV_te_customflash (void)
2056 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2057 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2059 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2060 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2062 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2063 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2064 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2066 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2068 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2070 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2071 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2072 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2073 SV_FlushBroadcastMessages();
2076 static void VM_SV_te_gunshot (void)
2078 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2079 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2080 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2082 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2083 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2084 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2085 SV_FlushBroadcastMessages();
2088 static void VM_SV_te_spike (void)
2090 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2091 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2092 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2094 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2095 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2096 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2097 SV_FlushBroadcastMessages();
2100 static void VM_SV_te_superspike (void)
2102 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2103 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2104 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2106 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2107 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2108 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2109 SV_FlushBroadcastMessages();
2112 static void VM_SV_te_explosion (void)
2114 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2115 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2116 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2118 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2119 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2120 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2121 SV_FlushBroadcastMessages();
2124 static void VM_SV_te_tarexplosion (void)
2126 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2127 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2128 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2130 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2131 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2132 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2133 SV_FlushBroadcastMessages();
2136 static void VM_SV_te_wizspike (void)
2138 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2139 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2140 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2142 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2143 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2144 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2145 SV_FlushBroadcastMessages();
2148 static void VM_SV_te_knightspike (void)
2150 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2151 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2152 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2154 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2155 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2156 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2157 SV_FlushBroadcastMessages();
2160 static void VM_SV_te_lavasplash (void)
2162 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2163 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2164 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2166 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2167 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2168 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2169 SV_FlushBroadcastMessages();
2172 static void VM_SV_te_teleport (void)
2174 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2175 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2176 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2178 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2179 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2180 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2181 SV_FlushBroadcastMessages();
2184 static void VM_SV_te_explosion2 (void)
2186 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2187 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2188 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2190 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2191 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2192 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2194 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2195 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2196 SV_FlushBroadcastMessages();
2199 static void VM_SV_te_lightning1 (void)
2201 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2202 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2203 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2205 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2207 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2208 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2209 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2211 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2212 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2213 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2214 SV_FlushBroadcastMessages();
2217 static void VM_SV_te_lightning2 (void)
2219 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2220 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2221 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2223 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2225 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2226 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2227 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2230 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2231 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2232 SV_FlushBroadcastMessages();
2235 static void VM_SV_te_lightning3 (void)
2237 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2238 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2239 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2241 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2243 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2244 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2245 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2247 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2248 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2249 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2250 SV_FlushBroadcastMessages();
2253 static void VM_SV_te_beam (void)
2255 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2256 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2257 MSG_WriteByte(&sv.datagram, TE_BEAM);
2259 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2261 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2262 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2263 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2265 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2266 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2267 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2268 SV_FlushBroadcastMessages();
2271 static void VM_SV_te_plasmaburn (void)
2273 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2274 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2275 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2276 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2277 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2278 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2279 SV_FlushBroadcastMessages();
2282 static void VM_SV_te_flamejet (void)
2284 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2285 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2286 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2288 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2289 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2290 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2292 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2293 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2294 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2296 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2297 SV_FlushBroadcastMessages();
2300 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2301 //this function originally written by KrimZon, made shorter by LordHavoc
2302 static void VM_SV_clientcommand (void)
2304 client_t *temp_client;
2306 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2308 //find client for this entity
2309 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2310 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2312 Con_Print("PF_clientcommand: entity is not a client\n");
2316 temp_client = host_client;
2317 host_client = svs.clients + i;
2318 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
2319 host_client = temp_client;
2322 //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)
2323 static void VM_SV_setattachment (void)
2325 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2326 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2327 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2330 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2332 if (e == prog->edicts)
2334 VM_Warning("setattachment: can not modify world entity\n");
2337 if (e->priv.server->free)
2339 VM_Warning("setattachment: can not modify free entity\n");
2343 if (tagentity == NULL)
2344 tagentity = prog->edicts;
2348 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2350 model = SV_GetModelFromEdict(tagentity);
2353 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2355 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);
2358 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));
2361 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2362 PRVM_serveredictfloat(e, tag_index) = tagindex;
2365 /////////////////////////////////////////
2366 // DP_MD3_TAGINFO extension coded by VorteX
2368 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2372 i = (int)PRVM_serveredictfloat(e, modelindex);
2373 if (i < 1 || i >= MAX_MODELS)
2376 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2379 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2386 Matrix4x4_CreateIdentity(tag_localmatrix);
2388 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2390 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2401 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2404 float pitchsign = 1;
2406 scale = PRVM_serveredictfloat(ent, scale);
2411 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);
2414 pitchsign = SV_GetPitchSign(ent);
2415 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);
2419 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2422 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2424 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2425 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2426 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2427 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2429 *out = identitymatrix;
2433 // Warnings/errors code:
2434 // 0 - normal (everything all-right)
2437 // 3 - null or non-precached model
2438 // 4 - no tags with requested index
2439 // 5 - runaway loop at attachment chain
2440 extern cvar_t cl_bob;
2441 extern cvar_t cl_bobcycle;
2442 extern cvar_t cl_bobup;
2443 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2446 int modelindex, attachloop;
2447 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2450 *out = identitymatrix; // warnings and errors return identical matrix
2452 if (ent == prog->edicts)
2454 if (ent->priv.server->free)
2457 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2458 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2461 model = SV_GetModelByIndex(modelindex);
2463 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2464 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2465 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2467 tagmatrix = identitymatrix;
2468 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2472 if (attachloop >= 256) // prevent runaway looping
2474 // apply transformation by child's tagindex on parent entity and then
2475 // by parent entity itself
2476 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2477 if (ret && attachloop == 0)
2479 SV_GetEntityMatrix(ent, &entitymatrix, false);
2480 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2481 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2482 // next iteration we process the parent entity
2483 if (PRVM_serveredictedict(ent, tag_entity))
2485 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2486 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2493 // RENDER_VIEWMODEL magic
2494 if (PRVM_serveredictedict(ent, viewmodelforclient))
2496 Matrix4x4_Copy(&tagmatrix, out);
2497 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2499 SV_GetEntityMatrix(ent, &entitymatrix, true);
2500 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2503 // Cl_bob, ported from rendering code
2504 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2507 // LordHavoc: this code is *weird*, but not replacable (I think it
2508 // should be done in QC on the server, but oh well, quake is quake)
2509 // LordHavoc: figured out bobup: the time at which the sin is at 180
2510 // degrees (which allows lengthening or squishing the peak or valley)
2511 cycle = sv.time/cl_bobcycle.value;
2512 cycle -= (int)cycle;
2513 if (cycle < cl_bobup.value)
2514 cycle = sin(M_PI * cycle / cl_bobup.value);
2516 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2517 // bob is proportional to velocity in the xy plane
2518 // (don't count Z, or jumping messes it up)
2519 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;
2520 bob = bob*0.3 + bob*0.7*cycle;
2521 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2528 //float(entity ent, string tagname) gettagindex;
2530 static void VM_SV_gettagindex (void)
2533 const char *tag_name;
2536 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2538 ent = PRVM_G_EDICT(OFS_PARM0);
2539 tag_name = PRVM_G_STRING(OFS_PARM1);
2541 if (ent == prog->edicts)
2543 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2546 if (ent->priv.server->free)
2548 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2553 if (!SV_GetModelFromEdict(ent))
2554 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2557 tag_index = SV_GetTagIndex(ent, tag_name);
2559 if(developer_extra.integer)
2560 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2562 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2565 //vector(entity ent, float tagindex) gettaginfo;
2566 static void VM_SV_gettaginfo (void)
2570 matrix4x4_t tag_matrix;
2571 matrix4x4_t tag_localmatrix;
2573 const char *tagname;
2575 vec3_t fo, le, up, trans;
2576 const dp_model_t *model;
2578 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2580 e = PRVM_G_EDICT(OFS_PARM0);
2581 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2583 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2584 Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
2585 VectorScale(le, -1, PRVM_serverglobalvector(v_right));
2586 model = SV_GetModelFromEdict(e);
2587 VM_GenerateFrameGroupBlend(e->priv.server->framegroupblend, e);
2588 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
2589 VM_UpdateEdictSkeleton(e, model, e->priv.server->frameblend);
2590 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2591 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2593 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2594 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(tagname) : 0;
2595 VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
2596 VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
2597 VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
2598 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2603 VM_Warning("gettagindex: can't affect world entity\n");
2606 VM_Warning("gettagindex: can't affect free entity\n");
2609 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2612 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2615 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2620 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2621 static void VM_SV_dropclient (void)
2624 client_t *oldhostclient;
2625 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2626 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2627 if (clientnum < 0 || clientnum >= svs.maxclients)
2629 VM_Warning("dropclient: not a client\n");
2632 if (!svs.clients[clientnum].active)
2634 VM_Warning("dropclient: that client slot is not connected\n");
2637 oldhostclient = host_client;
2638 host_client = svs.clients + clientnum;
2639 SV_DropClient(false);
2640 host_client = oldhostclient;
2643 //entity() spawnclient (DP_SV_BOTCLIENT)
2644 static void VM_SV_spawnclient (void)
2648 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2649 prog->xfunction->builtinsprofile += 2;
2651 for (i = 0;i < svs.maxclients;i++)
2653 if (!svs.clients[i].active)
2655 prog->xfunction->builtinsprofile += 100;
2656 SV_ConnectClient (i, NULL);
2657 // this has to be set or else ClientDisconnect won't be called
2658 // we assume the qc will call ClientConnect...
2659 svs.clients[i].clientconnectcalled = true;
2660 ed = PRVM_EDICT_NUM(i + 1);
2664 VM_RETURN_EDICT(ed);
2667 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2668 static void VM_SV_clienttype (void)
2671 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2672 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2673 if (clientnum < 0 || clientnum >= svs.maxclients)
2674 PRVM_G_FLOAT(OFS_RETURN) = 3;
2675 else if (!svs.clients[clientnum].active)
2676 PRVM_G_FLOAT(OFS_RETURN) = 0;
2677 else if (svs.clients[clientnum].netconnection)
2678 PRVM_G_FLOAT(OFS_RETURN) = 1;
2680 PRVM_G_FLOAT(OFS_RETURN) = 2;
2687 string(string key) serverkey
2690 void VM_SV_serverkey(void)
2692 char string[VM_STRINGTEMP_LENGTH];
2693 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2694 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2695 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2698 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2699 static void VM_SV_setmodelindex (void)
2704 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2706 e = PRVM_G_EDICT(OFS_PARM0);
2707 if (e == prog->edicts)
2709 VM_Warning("setmodelindex: can not modify world entity\n");
2712 if (e->priv.server->free)
2714 VM_Warning("setmodelindex: can not modify free entity\n");
2717 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2718 if (i <= 0 || i >= MAX_MODELS)
2720 VM_Warning("setmodelindex: invalid modelindex\n");
2723 if (!sv.model_precache[i][0])
2725 VM_Warning("setmodelindex: model not precached\n");
2729 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
2730 PRVM_serveredictfloat(e, modelindex) = i;
2732 mod = SV_GetModelByIndex(i);
2736 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2737 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2739 SetMinMaxSize (e, quakemins, quakemaxs, true);
2742 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2745 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2746 static void VM_SV_modelnameforindex (void)
2749 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2751 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2753 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2754 if (i <= 0 || i >= MAX_MODELS)
2756 VM_Warning("modelnameforindex: invalid modelindex\n");
2759 if (!sv.model_precache[i][0])
2761 VM_Warning("modelnameforindex: model not precached\n");
2765 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2768 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2769 static void VM_SV_particleeffectnum (void)
2772 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2773 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2776 PRVM_G_FLOAT(OFS_RETURN) = i;
2779 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2780 static void VM_SV_trailparticles (void)
2782 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2784 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2787 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2788 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2789 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2790 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2791 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2792 SV_FlushBroadcastMessages();
2795 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2796 static void VM_SV_pointparticles (void)
2798 int effectnum, count;
2800 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2802 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2805 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2806 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2807 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2808 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2809 if (count == 1 && !VectorLength2(vel))
2812 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2813 MSG_WriteShort(&sv.datagram, effectnum);
2814 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2818 // 1+2+12+12+2=29 bytes
2819 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2820 MSG_WriteShort(&sv.datagram, effectnum);
2821 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2822 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2823 MSG_WriteShort(&sv.datagram, count);
2826 SV_FlushBroadcastMessages();
2829 //PF_setpause, // void(float pause) setpause = #531;
2830 static void VM_SV_setpause(void) {
2832 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2833 if (pauseValue != 0) { //pause the game
2835 sv.pausedstart = Sys_DoubleTime();
2836 } else { //disable pause, in case it was enabled
2837 if (sv.paused != 0) {
2842 // send notification to all clients
2843 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2844 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2847 // #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.
2848 static void VM_SV_skel_create(void)
2850 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2851 dp_model_t *model = SV_GetModelByIndex(modelindex);
2852 skeleton_t *skeleton;
2854 PRVM_G_FLOAT(OFS_RETURN) = 0;
2855 if (!model || !model->num_bones)
2857 for (i = 0;i < MAX_EDICTS;i++)
2858 if (!prog->skeletons[i])
2860 if (i == MAX_EDICTS)
2862 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2863 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2864 skeleton->model = model;
2865 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2866 // initialize to identity matrices
2867 for (i = 0;i < skeleton->model->num_bones;i++)
2868 skeleton->relativetransforms[i] = identitymatrix;
2871 // #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
2872 static void VM_SV_skel_build(void)
2874 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2875 skeleton_t *skeleton;
2876 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2877 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2878 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2879 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2880 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2881 dp_model_t *model = SV_GetModelByIndex(modelindex);
2886 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2887 frameblend_t frameblend[MAX_FRAMEBLENDS];
2888 matrix4x4_t blendedmatrix;
2890 PRVM_G_FLOAT(OFS_RETURN) = 0;
2891 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2893 firstbone = max(0, firstbone);
2894 lastbone = min(lastbone, model->num_bones - 1);
2895 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2896 VM_GenerateFrameGroupBlend(framegroupblend, ed);
2897 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
2898 blendfrac = 1.0f - retainfrac;
2899 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2900 frameblend[numblends].lerp *= blendfrac;
2901 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2903 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2904 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2905 for (blendindex = 0;blendindex < numblends;blendindex++)
2907 Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2908 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2910 skeleton->relativetransforms[bonenum] = blendedmatrix;
2912 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2915 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2916 static void VM_SV_skel_get_numbones(void)
2918 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2919 skeleton_t *skeleton;
2920 PRVM_G_FLOAT(OFS_RETURN) = 0;
2921 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2923 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2926 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2927 static void VM_SV_skel_get_bonename(void)
2929 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2930 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2931 skeleton_t *skeleton;
2932 PRVM_G_INT(OFS_RETURN) = 0;
2933 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2935 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2937 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(skeleton->model->data_bones[bonenum].name);
2940 // #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)
2941 static void VM_SV_skel_get_boneparent(void)
2943 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2944 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2945 skeleton_t *skeleton;
2946 PRVM_G_FLOAT(OFS_RETURN) = 0;
2947 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2949 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2951 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2954 // #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
2955 static void VM_SV_skel_find_bone(void)
2957 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2958 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2959 skeleton_t *skeleton;
2960 PRVM_G_FLOAT(OFS_RETURN) = 0;
2961 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2963 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2966 // #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)
2967 static void VM_SV_skel_get_bonerel(void)
2969 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2970 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2971 skeleton_t *skeleton;
2973 vec3_t forward, left, up, origin;
2974 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2975 VectorClear(PRVM_clientglobalvector(v_forward));
2976 VectorClear(PRVM_clientglobalvector(v_right));
2977 VectorClear(PRVM_clientglobalvector(v_up));
2978 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2980 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2982 matrix = skeleton->relativetransforms[bonenum];
2983 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2984 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2985 VectorNegate(left, PRVM_clientglobalvector(v_right));
2986 VectorCopy(up, PRVM_clientglobalvector(v_up));
2987 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2990 // #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)
2991 static void VM_SV_skel_get_boneabs(void)
2993 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2994 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2995 skeleton_t *skeleton;
2998 vec3_t forward, left, up, origin;
2999 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3000 VectorClear(PRVM_clientglobalvector(v_forward));
3001 VectorClear(PRVM_clientglobalvector(v_right));
3002 VectorClear(PRVM_clientglobalvector(v_up));
3003 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3005 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3007 matrix = skeleton->relativetransforms[bonenum];
3008 // convert to absolute
3009 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3012 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3014 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3015 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3016 VectorNegate(left, PRVM_clientglobalvector(v_right));
3017 VectorCopy(up, PRVM_clientglobalvector(v_up));
3018 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3021 // #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)
3022 static void VM_SV_skel_set_bone(void)
3024 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3025 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3026 vec3_t forward, left, up, origin;
3027 skeleton_t *skeleton;
3029 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3031 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3033 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3034 VectorNegate(PRVM_clientglobalvector(v_right), left);
3035 VectorCopy(PRVM_clientglobalvector(v_up), up);
3036 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3037 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3038 skeleton->relativetransforms[bonenum] = matrix;
3041 // #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)
3042 static void VM_SV_skel_mul_bone(void)
3044 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3045 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3046 vec3_t forward, left, up, origin;
3047 skeleton_t *skeleton;
3050 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3052 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3054 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3055 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3056 VectorNegate(PRVM_clientglobalvector(v_right), left);
3057 VectorCopy(PRVM_clientglobalvector(v_up), up);
3058 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3059 temp = skeleton->relativetransforms[bonenum];
3060 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3063 // #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)
3064 static void VM_SV_skel_mul_bones(void)
3066 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3067 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3068 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3070 vec3_t forward, left, up, origin;
3071 skeleton_t *skeleton;
3074 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3076 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3077 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3078 VectorNegate(PRVM_clientglobalvector(v_right), left);
3079 VectorCopy(PRVM_clientglobalvector(v_up), up);
3080 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3081 firstbone = max(0, firstbone);
3082 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3083 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3085 temp = skeleton->relativetransforms[bonenum];
3086 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3090 // #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
3091 static void VM_SV_skel_copybones(void)
3093 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3094 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3095 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3096 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3098 skeleton_t *skeletondst;
3099 skeleton_t *skeletonsrc;
3100 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3102 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3104 firstbone = max(0, firstbone);
3105 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3106 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3107 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3108 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3111 // #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)
3112 static void VM_SV_skel_delete(void)
3114 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3115 skeleton_t *skeleton;
3116 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3119 prog->skeletons[skeletonindex] = NULL;
3122 // #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
3123 static void VM_SV_frameforname(void)
3125 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3126 dp_model_t *model = SV_GetModelByIndex(modelindex);
3127 const char *name = PRVM_G_STRING(OFS_PARM1);
3129 PRVM_G_FLOAT(OFS_RETURN) = -1;
3130 if (!model || !model->animscenes)
3132 for (i = 0;i < model->numframes;i++)
3134 if (!strcasecmp(model->animscenes[i].name, name))
3136 PRVM_G_FLOAT(OFS_RETURN) = i;
3142 // #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.
3143 static void VM_SV_frameduration(void)
3145 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3146 dp_model_t *model = SV_GetModelByIndex(modelindex);
3147 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3148 PRVM_G_FLOAT(OFS_RETURN) = 0;
3149 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3151 if (model->animscenes[framenum].framerate)
3152 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3156 prvm_builtin_t vm_sv_builtins[] = {
3157 NULL, // #0 NULL function (not callable) (QUAKE)
3158 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3159 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3160 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3161 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3162 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3163 VM_break, // #6 void() break (QUAKE)
3164 VM_random, // #7 float() random (QUAKE)
3165 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3166 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3167 VM_error, // #10 void(string e) error (QUAKE)
3168 VM_objerror, // #11 void(string e) objerror (QUAKE)
3169 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3170 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3171 VM_spawn, // #14 entity() spawn (QUAKE)
3172 VM_remove, // #15 void(entity e) remove (QUAKE)
3173 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3174 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3175 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3176 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3177 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3178 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3179 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3180 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3181 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3182 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3183 VM_ftos, // #26 string(float f) ftos (QUAKE)
3184 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3185 VM_coredump, // #28 void() coredump (QUAKE)
3186 VM_traceon, // #29 void() traceon (QUAKE)
3187 VM_traceoff, // #30 void() traceoff (QUAKE)
3188 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3189 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3190 NULL, // #33 (QUAKE)
3191 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3192 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3193 VM_rint, // #36 float(float v) rint (QUAKE)
3194 VM_floor, // #37 float(float v) floor (QUAKE)
3195 VM_ceil, // #38 float(float v) ceil (QUAKE)
3196 NULL, // #39 (QUAKE)
3197 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3198 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3199 NULL, // #42 (QUAKE)
3200 VM_fabs, // #43 float(float f) fabs (QUAKE)
3201 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3202 VM_cvar, // #45 float(string s) cvar (QUAKE)
3203 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3204 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3205 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3206 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3207 NULL, // #50 (QUAKE)
3208 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3209 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3210 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3211 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3212 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3213 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3214 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3215 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3216 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3217 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3218 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3219 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3220 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3221 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3222 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3223 NULL, // #66 (QUAKE)
3224 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3225 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3226 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3227 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3228 NULL, // #71 (QUAKE)
3229 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3230 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3231 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3232 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3233 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3234 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3235 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3236 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3237 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3238 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3239 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3240 NULL, // #83 (QUAKE)
3241 NULL, // #84 (QUAKE)
3242 NULL, // #85 (QUAKE)
3243 NULL, // #86 (QUAKE)
3244 NULL, // #87 (QUAKE)
3245 NULL, // #88 (QUAKE)
3246 NULL, // #89 (QUAKE)
3247 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3248 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3249 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3250 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3251 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3252 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3253 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3254 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3255 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3256 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3257 // FrikaC and Telejano range #100-#199
3268 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3269 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3270 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3271 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3272 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3273 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3274 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3275 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3276 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3277 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3358 // FTEQW range #200-#299
3377 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3380 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3381 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3382 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3383 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3384 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3385 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3386 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3387 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3388 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3389 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3391 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3399 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3422 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.
3423 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
3424 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3425 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3426 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)
3427 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
3428 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)
3429 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)
3430 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)
3431 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)
3432 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)
3433 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
3434 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)
3435 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
3436 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.
3459 // CSQC range #300-#399
3460 NULL, // #300 void() clearscene (EXT_CSQC)
3461 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3462 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3463 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3464 NULL, // #304 void() renderscene (EXT_CSQC)
3465 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3466 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3467 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3468 NULL, // #308 void() R_EndPolygon
3470 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3471 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3475 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3476 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3477 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3478 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3479 NULL, // #319 void(string name) freepic (EXT_CSQC)
3480 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3481 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3482 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3483 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3484 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3485 NULL, // #325 void(void) drawresetcliparea
3490 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3491 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3492 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3493 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3494 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3495 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3496 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3497 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3498 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3499 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3500 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3501 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3502 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3503 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3504 NULL, // #344 vector() getmousepos (EXT_CSQC)
3505 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3506 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3507 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3508 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3509 NULL, // #349 float() isdemo (EXT_CSQC)
3510 VM_isserver, // #350 float() isserver (EXT_CSQC)
3511 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3512 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3513 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3514 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3520 NULL, // #360 float() readbyte (EXT_CSQC)
3521 NULL, // #361 float() readchar (EXT_CSQC)
3522 NULL, // #362 float() readshort (EXT_CSQC)
3523 NULL, // #363 float() readlong (EXT_CSQC)
3524 NULL, // #364 float() readcoord (EXT_CSQC)
3525 NULL, // #365 float() readangle (EXT_CSQC)
3526 NULL, // #366 string() readstring (EXT_CSQC)
3527 NULL, // #367 float() readfloat (EXT_CSQC)
3560 // LordHavoc's range #400-#499
3561 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3562 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3563 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3564 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3565 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3566 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3567 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3568 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3569 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)
3570 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3571 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3572 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3573 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3574 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3575 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3576 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3577 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3578 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3579 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3580 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3581 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3582 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3583 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3584 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3585 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3586 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3587 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3588 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3589 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3590 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3591 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3592 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3593 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3594 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3595 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3596 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3597 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3598 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3599 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3600 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3601 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3602 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3603 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3604 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3605 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3606 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3607 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3608 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3609 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3610 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3611 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3612 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3613 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3614 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3615 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3616 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3617 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3618 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3620 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3621 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3622 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3623 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3624 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3625 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3626 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3627 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3628 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3629 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3630 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3632 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3633 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3634 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3635 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3636 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3637 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3638 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3639 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3640 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3641 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3642 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3643 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3644 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3645 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3646 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3647 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3655 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3656 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3657 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3658 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3659 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3660 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3661 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3662 VM_SV_WritePicture, // #501
3664 VM_whichpack, // #503 string(string) whichpack = #503;
3671 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3672 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3673 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3674 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)
3675 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3676 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3677 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3678 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3679 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3680 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3690 VM_loadfromdata, // #529
3691 VM_loadfromfile, // #530
3692 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3694 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3695 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3701 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3702 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3703 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3766 VM_callfunction, // #605
3767 VM_writetofile, // #606
3768 VM_isfunction, // #607
3774 VM_parseentitydata, // #613
3785 VM_SV_getextresponse, // #624 string getextresponse(void)
3788 VM_sprintf, // #627 string sprintf(string format, ...)
3789 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3790 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3800 VM_digest_hex, // #639
3804 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3806 void VM_SV_Cmd_Init(void)
3811 void VM_SV_Cmd_Reset(void)
3813 World_End(&sv.world);
3814 if(PRVM_serverfunction(SV_Shutdown))
3816 func_t s = PRVM_serverfunction(SV_Shutdown);
3817 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3818 PRVM_ExecuteProgram(s,"SV_Shutdown() required");