6 //============================================================================
11 const char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
24 "DP_CSQC_ENTITYWORLDOBJECT "
25 "DP_CSQC_ENTITYMODELLIGHT "
26 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
27 "DP_CSQC_MULTIFRAME_INTERPOLATION "
28 "DP_CSQC_BOXPARTICLES "
29 "DP_CSQC_SPAWNPARTICLE "
30 "DP_CSQC_QUERYRENDERENTITY "
31 "DP_CSQC_ROTATEMOVES "
44 "DP_EF_RESTARTANIM_BIT "
49 "DP_ENT_CUSTOMCOLORMAP "
50 "DP_ENT_EXTERIORMODELTOCLIENT "
53 "DP_ENT_LOWPRECISION "
55 "DP_ENT_TRAILEFFECTNUM "
58 "DP_GFX_EXTERNALTEXTURES "
59 "DP_GFX_EXTERNALTEXTURES_PERMAP "
61 "DP_GFX_MODEL_INTERPOLATION "
62 "DP_GFX_QUAKE3MODELTAGS "
66 "DP_GFX_FONTS_FREETYPE "
68 "DP_FONT_VARIABLEWIDTH "
70 "DP_HALFLIFE_MAP_CVAR "
73 "DP_LIGHTSTYLE_STATICVALUE "
77 "DP_MOVETYPEBOUNCEMISSILE "
78 "DP_MOVETYPEFLYWORLDONLY "
81 "DP_QC_ASINACOSATANATAN2TAN "
87 "DP_QC_CVAR_DEFSTRING "
88 "DP_QC_CVAR_DESCRIPTION "
95 "DP_QC_EXTRESPONSEPACKET "
97 "DP_QC_FINDCHAINFLAGS "
98 "DP_QC_FINDCHAINFLOAT "
99 "DP_QC_FINDCHAIN_TOFIELD "
105 "DP_QC_GETSURFACETRIANGLE "
106 "DP_QC_GETSURFACEPOINTATTRIBUTE "
108 "DP_QC_GETTAGINFO_BONEPROPERTIES "
110 "DP_QC_GETTIME_CDTRACK "
114 "DP_QC_MULTIPLETEMPSTRINGS "
115 "DP_QC_NUM_FOR_EDICT "
117 "DP_QC_SINCOSSQRTPOW "
120 "DP_QC_STRINGBUFFERS "
121 "DP_QC_STRINGBUFFERS_CVARLIST "
122 "DP_QC_STRINGCOLORFUNCTIONS "
123 "DP_QC_STRING_CASE_FUNCTIONS "
125 "DP_QC_TOKENIZEBYSEPARATOR "
126 "DP_QC_TOKENIZE_CONSOLE "
129 "DP_QC_TRACE_MOVETYPE_HITMODEL "
130 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
131 "DP_QC_UNLIMITEDTEMPSTRINGS "
135 "DP_QC_VECTOANGLES_WITH_ROLL "
136 "DP_QC_VECTORVECTORS "
143 "DP_SKELETONOBJECTS "
144 "DP_SND_DIRECTIONLESSATTNNONE "
146 "DP_SND_SOUND7_WIP1 "
147 "DP_SND_SOUND7_WIP2 "
151 "DP_SND_GETSOUNDTIME "
153 "DP_VIDEO_SUBTITLES "
157 "DP_SV_BOUNCEFACTOR "
158 "DP_SV_CLIENTCAMERA "
159 "DP_SV_CLIENTCOLORS "
162 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
163 "DP_SV_DISCARDABLEDEMO "
164 "DP_SV_DRAWONLYTOCLIENT "
167 "DP_SV_ENTITYCONTENTSTRANSITION "
168 "DP_SV_MODELFLAGS_AS_EFFECTS "
169 "DP_SV_MOVETYPESTEP_LANDEVENT "
171 "DP_SV_NODRAWTOCLIENT "
172 "DP_SV_ONENTITYNOSPAWNFUNCTION "
173 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
175 "DP_SV_PING_PACKETLOSS "
176 "DP_SV_PLAYERPHYSICS "
178 "DP_SV_POINTPARTICLES "
180 "DP_SV_PRECACHEANYTIME "
184 "DP_SV_ROTATINGBMODEL "
188 "DP_SV_SPAWNFUNC_PREFIX "
189 "DP_SV_WRITEPICTURE "
190 "DP_SV_WRITEUNTERMINATEDSTRING "
194 "DP_TE_EXPLOSIONRGB "
196 "DP_TE_PARTICLECUBE "
197 "DP_TE_PARTICLERAIN "
198 "DP_TE_PARTICLESNOW "
200 "DP_TE_QUADEFFECTS1 "
203 "DP_TE_STANDARDEFFECTBUILTINS "
204 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
208 "FTE_CSQC_SKELETONOBJECTS "
211 "KRIMZON_SV_PARSECLIENTCOMMAND "
214 "NEXUIZ_PLAYERMODEL "
216 "PRYDON_CLIENTCURSOR "
217 "TENEBRAE_GFX_DLIGHTS "
220 //"EXT_CSQC " // not ready yet
227 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.
229 setorigin (entity, origin)
232 static void VM_SV_setorigin (void)
237 VM_SAFEPARMCOUNT(2, VM_setorigin);
239 e = PRVM_G_EDICT(OFS_PARM0);
240 if (e == prog->edicts)
242 VM_Warning("setorigin: can not modify world entity\n");
245 if (e->priv.server->free)
247 VM_Warning("setorigin: can not modify free entity\n");
250 org = PRVM_G_VECTOR(OFS_PARM1);
251 VectorCopy (org, PRVM_serveredictvector(e, origin));
255 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
256 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
260 for (i=0 ; i<3 ; i++)
262 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
264 // set derived values
265 VectorCopy (min, PRVM_serveredictvector(e, mins));
266 VectorCopy (max, PRVM_serveredictvector(e, maxs));
267 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
276 the size box is rotated by the current angle
277 LordHavoc: no it isn't...
279 setsize (entity, minvector, maxvector)
282 static void VM_SV_setsize (void)
287 VM_SAFEPARMCOUNT(3, VM_setsize);
289 e = PRVM_G_EDICT(OFS_PARM0);
290 if (e == prog->edicts)
292 VM_Warning("setsize: can not modify world entity\n");
295 if (e->priv.server->free)
297 VM_Warning("setsize: can not modify free entity\n");
300 min = PRVM_G_VECTOR(OFS_PARM1);
301 max = PRVM_G_VECTOR(OFS_PARM2);
302 SetMinMaxSize (e, min, max, false);
310 setmodel(entity, model)
313 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
314 static void VM_SV_setmodel (void)
320 VM_SAFEPARMCOUNT(2, VM_setmodel);
322 e = PRVM_G_EDICT(OFS_PARM0);
323 if (e == prog->edicts)
325 VM_Warning("setmodel: can not modify world entity\n");
328 if (e->priv.server->free)
330 VM_Warning("setmodel: can not modify free entity\n");
333 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
334 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
335 PRVM_serveredictfloat(e, modelindex) = i;
337 mod = SV_GetModelByIndex(i);
341 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
342 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
344 SetMinMaxSize (e, quakemins, quakemaxs, true);
347 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
354 single print to a specific client
356 sprint(clientent, value)
359 static void VM_SV_sprint (void)
363 char string[VM_STRINGTEMP_LENGTH];
365 VM_VarString(1, string, sizeof(string));
367 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
369 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
370 // LordHavoc: div0 requested that sprintto world operate like print
377 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
379 VM_Warning("tried to centerprint to a non-client\n");
383 client = svs.clients + entnum-1;
384 if (!client->netconnection)
387 MSG_WriteChar(&client->netconnection->message,svc_print);
388 MSG_WriteString(&client->netconnection->message, string);
396 single print to a specific client
398 centerprint(clientent, value)
401 static void VM_SV_centerprint (void)
405 char string[VM_STRINGTEMP_LENGTH];
407 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
409 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
411 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
413 VM_Warning("tried to centerprint to a non-client\n");
417 client = svs.clients + entnum-1;
418 if (!client->netconnection)
421 VM_VarString(1, string, sizeof(string));
422 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
423 MSG_WriteString(&client->netconnection->message, string);
430 particle(origin, color, count)
433 static void VM_SV_particle (void)
439 VM_SAFEPARMCOUNT(4, VM_SV_particle);
441 org = PRVM_G_VECTOR(OFS_PARM0);
442 dir = PRVM_G_VECTOR(OFS_PARM1);
443 color = PRVM_G_FLOAT(OFS_PARM2);
444 count = PRVM_G_FLOAT(OFS_PARM3);
445 SV_StartParticle (org, dir, (int)color, (int)count);
455 static void VM_SV_ambientsound (void)
459 float vol, attenuation;
462 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
464 pos = PRVM_G_VECTOR (OFS_PARM0);
465 samp = PRVM_G_STRING(OFS_PARM1);
466 vol = PRVM_G_FLOAT(OFS_PARM2);
467 attenuation = PRVM_G_FLOAT(OFS_PARM3);
469 // check to see if samp was properly precached
470 soundnum = SV_SoundIndex(samp, 1);
478 // add an svc_spawnambient command to the level signon packet
481 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
483 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
485 MSG_WriteVector(&sv.signon, pos, sv.protocol);
487 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
488 MSG_WriteShort (&sv.signon, soundnum);
490 MSG_WriteByte (&sv.signon, soundnum);
492 MSG_WriteByte (&sv.signon, (int)(vol*255));
493 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
501 Each entity can have eight independant sound sources, like voice,
504 Channel 0 is an auto-allocate channel, the others override anything
505 already running on that entity/channel pair.
507 An attenuation of 0 will play full volume everywhere in the level.
508 Larger attenuations will drop off.
512 static void VM_SV_sound (void)
516 prvm_edict_t *entity;
522 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
524 entity = PRVM_G_EDICT(OFS_PARM0);
525 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
526 sample = PRVM_G_STRING(OFS_PARM2);
527 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
530 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
534 attenuation = PRVM_G_FLOAT(OFS_PARM4);
538 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
543 if(channel >= 8 && channel <= 15) // weird QW feature
545 flags |= CHANFLAG_RELIABLE;
550 flags = PRVM_G_FLOAT(OFS_PARM6);
552 if (volume < 0 || volume > 255)
554 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
558 if (attenuation < 0 || attenuation > 4)
560 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
564 channel = CHAN_USER2ENGINE(channel);
566 if (!IS_CHAN(channel))
568 VM_Warning("SV_StartSound: channel must be in range 0-127\n");
572 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE, pitchchange);
579 Follows the same logic as VM_SV_sound, except instead of
580 an entity, an origin for the sound is provided, and channel
581 is omitted (since no entity is being tracked).
585 static void VM_SV_pointsound(void)
593 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
595 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
596 sample = PRVM_G_STRING(OFS_PARM1);
597 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
598 attenuation = PRVM_G_FLOAT(OFS_PARM3);
599 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
601 if (volume < 0 || volume > 255)
603 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
607 if (attenuation < 0 || attenuation > 4)
609 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
613 SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
620 Used for use tracing and shot targeting
621 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
622 if the tryents flag is set.
624 traceline (vector1, vector2, movetype, ignore)
627 static void VM_SV_traceline (void)
634 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
636 prog->xfunction->builtinsprofile += 30;
638 v1 = PRVM_G_VECTOR(OFS_PARM0);
639 v2 = PRVM_G_VECTOR(OFS_PARM1);
640 move = (int)PRVM_G_FLOAT(OFS_PARM2);
641 ent = PRVM_G_EDICT(OFS_PARM3);
643 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]))
644 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));
646 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
648 VM_SetTraceGlobals(&trace);
656 Used for use tracing and shot targeting
657 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
658 if the tryents flag is set.
660 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
663 // LordHavoc: added this for my own use, VERY useful, similar to traceline
664 static void VM_SV_tracebox (void)
666 float *v1, *v2, *m1, *m2;
671 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
673 prog->xfunction->builtinsprofile += 30;
675 v1 = PRVM_G_VECTOR(OFS_PARM0);
676 m1 = PRVM_G_VECTOR(OFS_PARM1);
677 m2 = PRVM_G_VECTOR(OFS_PARM2);
678 v2 = PRVM_G_VECTOR(OFS_PARM3);
679 move = (int)PRVM_G_FLOAT(OFS_PARM4);
680 ent = PRVM_G_EDICT(OFS_PARM5);
682 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]))
683 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));
685 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
687 VM_SetTraceGlobals(&trace);
690 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
695 vec3_t original_origin;
696 vec3_t original_velocity;
697 vec3_t original_angles;
698 vec3_t original_avelocity;
701 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
702 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
703 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
704 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
706 gravity = PRVM_serveredictfloat(tossent, gravity);
709 gravity *= sv_gravity.value * 0.025;
711 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
713 SV_CheckVelocity (tossent);
714 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
715 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
716 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
717 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
718 trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
719 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
720 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
722 if (trace.fraction < 1)
726 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
727 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
728 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
729 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
734 static void VM_SV_tracetoss (void)
738 prvm_edict_t *ignore;
740 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
742 prog->xfunction->builtinsprofile += 600;
744 ent = PRVM_G_EDICT(OFS_PARM0);
745 if (ent == prog->edicts)
747 VM_Warning("tracetoss: can not use world entity\n");
750 ignore = PRVM_G_EDICT(OFS_PARM1);
752 trace = SV_Trace_Toss (ent, ignore);
754 VM_SetTraceGlobals(&trace);
757 //============================================================================
759 static int checkpvsbytes;
760 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
762 static int VM_SV_newcheckclient (int check)
768 // cycle to the next one
770 check = bound(1, check, svs.maxclients);
771 if (check == svs.maxclients)
779 prog->xfunction->builtinsprofile++;
781 if (i == svs.maxclients+1)
783 // look up the client's edict
784 ent = PRVM_EDICT_NUM(i);
785 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
786 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
788 // found a valid client (possibly the same one again)
792 // get the PVS for the entity
793 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
795 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
796 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
805 Returns a client (or object that has a client enemy) that would be a
808 If there is more than one valid option, they are cycled each frame
810 If (self.origin + self.viewofs) is not in the PVS of the current target,
811 it is not returned at all.
816 int c_invis, c_notvis;
817 static void VM_SV_checkclient (void)
819 prvm_edict_t *ent, *self;
822 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
824 // find a new check if on a new frame
825 if (sv.time - sv.lastchecktime >= 0.1)
827 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
828 sv.lastchecktime = sv.time;
831 // return check if it might be visible
832 ent = PRVM_EDICT_NUM(sv.lastcheck);
833 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
835 VM_RETURN_EDICT(prog->edicts);
839 // if current entity can't possibly see the check entity, return 0
840 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
841 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
842 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
845 VM_RETURN_EDICT(prog->edicts);
849 // might be able to see it
851 VM_RETURN_EDICT(ent);
854 //============================================================================
860 Checks if an entity is in a point's PVS.
861 Should be fast but can be inexact.
863 float checkpvs(vector viewpos, entity viewee) = #240;
866 static void VM_SV_checkpvs (void)
869 prvm_edict_t *viewee;
874 unsigned char fatpvs[MAX_MAP_LEAFS/8];
877 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
878 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
879 viewee = PRVM_G_EDICT(OFS_PARM1);
881 if(viewee->priv.server->free)
883 VM_Warning("checkpvs: can not check free entity\n");
884 PRVM_G_FLOAT(OFS_RETURN) = 4;
889 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
891 // no PVS support on this worldmodel... darn
892 PRVM_G_FLOAT(OFS_RETURN) = 3;
895 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
898 // viewpos isn't in any PVS... darn
899 PRVM_G_FLOAT(OFS_RETURN) = 2;
902 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
904 // using fat PVS like FTEQW does (slow)
905 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
907 // no PVS support on this worldmodel... darn
908 PRVM_G_FLOAT(OFS_RETURN) = 3;
911 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
914 // viewpos isn't in any PVS... darn
915 PRVM_G_FLOAT(OFS_RETURN) = 2;
918 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
927 Sends text over to the client's execution buffer
929 stuffcmd (clientent, value, ...)
932 static void VM_SV_stuffcmd (void)
936 char string[VM_STRINGTEMP_LENGTH];
938 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
940 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
941 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
943 VM_Warning("Can't stuffcmd to a non-client\n");
947 VM_VarString(1, string, sizeof(string));
950 host_client = svs.clients + entnum-1;
951 Host_ClientCommands ("%s", string);
959 Returns a chain of entities that have origins within a spherical area
961 findradius (origin, radius)
964 static void VM_SV_findradius (void)
966 prvm_edict_t *ent, *chain;
967 vec_t radius, radius2;
968 vec3_t org, eorg, mins, maxs;
971 static prvm_edict_t *touchedicts[MAX_EDICTS];
974 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
977 chainfield = PRVM_G_INT(OFS_PARM2);
979 chainfield = prog->fieldoffsets.chain;
981 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
983 chain = (prvm_edict_t *)prog->edicts;
985 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
986 radius = PRVM_G_FLOAT(OFS_PARM1);
987 radius2 = radius * radius;
989 mins[0] = org[0] - (radius + 1);
990 mins[1] = org[1] - (radius + 1);
991 mins[2] = org[2] - (radius + 1);
992 maxs[0] = org[0] + (radius + 1);
993 maxs[1] = org[1] + (radius + 1);
994 maxs[2] = org[2] + (radius + 1);
995 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
996 if (numtouchedicts > MAX_EDICTS)
998 // this never happens
999 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1000 numtouchedicts = MAX_EDICTS;
1002 for (i = 0;i < numtouchedicts;i++)
1004 ent = touchedicts[i];
1005 prog->xfunction->builtinsprofile++;
1006 // Quake did not return non-solid entities but darkplaces does
1007 // (note: this is the reason you can't blow up fallen zombies)
1008 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1010 // LordHavoc: compare against bounding box rather than center so it
1011 // doesn't miss large objects, and use DotProduct instead of Length
1012 // for a major speedup
1013 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1014 if (sv_gameplayfix_findradiusdistancetobox.integer)
1016 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1017 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1018 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1021 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1022 if (DotProduct(eorg, eorg) < radius2)
1024 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1029 VM_RETURN_EDICT(chain);
1032 static void VM_SV_precache_sound (void)
1034 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1035 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1038 static void VM_SV_precache_model (void)
1040 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1041 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1042 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1049 float(float yaw, float dist[, settrace]) walkmove
1052 static void VM_SV_walkmove (void)
1061 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1063 // assume failure if it returns early
1064 PRVM_G_FLOAT(OFS_RETURN) = 0;
1066 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1067 if (ent == prog->edicts)
1069 VM_Warning("walkmove: can not modify world entity\n");
1072 if (ent->priv.server->free)
1074 VM_Warning("walkmove: can not modify free entity\n");
1077 yaw = PRVM_G_FLOAT(OFS_PARM0);
1078 dist = PRVM_G_FLOAT(OFS_PARM1);
1079 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1081 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1084 yaw = yaw*M_PI*2 / 360;
1086 move[0] = cos(yaw)*dist;
1087 move[1] = sin(yaw)*dist;
1090 // save program state, because SV_movestep may call other progs
1091 oldf = prog->xfunction;
1092 oldself = PRVM_serverglobaledict(self);
1094 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1097 // restore program state
1098 prog->xfunction = oldf;
1099 PRVM_serverglobaledict(self) = oldself;
1110 static void VM_SV_droptofloor (void)
1116 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1118 // assume failure if it returns early
1119 PRVM_G_FLOAT(OFS_RETURN) = 0;
1121 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1122 if (ent == prog->edicts)
1124 VM_Warning("droptofloor: can not modify world entity\n");
1127 if (ent->priv.server->free)
1129 VM_Warning("droptofloor: can not modify free entity\n");
1133 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1136 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1137 if (sv_gameplayfix_unstickentities.integer)
1138 SV_UnstickEntity(ent);
1140 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1141 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1144 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]);
1145 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1146 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1147 VectorSubtract(trace.endpos, offset, trace.endpos);
1148 if (trace.startsolid)
1150 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]);
1151 if (sv_gameplayfix_unstickentities.integer)
1152 SV_UnstickEntity(ent);
1154 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1155 PRVM_serveredictedict(ent, groundentity) = 0;
1156 PRVM_G_FLOAT(OFS_RETURN) = 1;
1158 else if (trace.fraction < 1)
1160 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]);
1161 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1162 if (sv_gameplayfix_unstickentities.integer)
1163 SV_UnstickEntity(ent);
1165 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1166 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1167 PRVM_G_FLOAT(OFS_RETURN) = 1;
1168 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1169 ent->priv.server->suspendedinairflag = true;
1174 if (trace.fraction != 1)
1176 if (trace.fraction < 1)
1177 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1179 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1180 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1181 PRVM_G_FLOAT(OFS_RETURN) = 1;
1182 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1183 ent->priv.server->suspendedinairflag = true;
1192 void(float style, string value) lightstyle
1195 static void VM_SV_lightstyle (void)
1202 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1204 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1205 val = PRVM_G_STRING(OFS_PARM1);
1207 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1208 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1211 // change the string in sv
1212 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1214 // send message to all clients on this server
1215 if (sv.state != ss_active)
1218 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1220 if (client->active && client->netconnection)
1222 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1223 MSG_WriteChar (&client->netconnection->message,style);
1224 MSG_WriteString (&client->netconnection->message, val);
1234 static void VM_SV_checkbottom (void)
1236 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1237 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1245 static void VM_SV_pointcontents (void)
1247 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1248 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1255 Pick a vector for the player to shoot along
1256 vector aim(entity, missilespeed)
1259 static void VM_SV_aim (void)
1261 prvm_edict_t *ent, *check, *bestent;
1262 vec3_t start, dir, end, bestdir;
1265 float dist, bestdist;
1268 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1270 // assume failure if it returns early
1271 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1272 // if sv_aim is so high it can't possibly accept anything, skip out early
1273 if (sv_aim.value >= 1)
1276 ent = PRVM_G_EDICT(OFS_PARM0);
1277 if (ent == prog->edicts)
1279 VM_Warning("aim: can not use world entity\n");
1282 if (ent->priv.server->free)
1284 VM_Warning("aim: can not use free entity\n");
1287 //speed = PRVM_G_FLOAT(OFS_PARM1);
1289 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1292 // try sending a trace straight
1293 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1294 VectorMA (start, 2048, dir, end);
1295 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1296 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1297 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1299 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1304 // try all possible entities
1305 VectorCopy (dir, bestdir);
1306 bestdist = sv_aim.value;
1309 check = PRVM_NEXT_EDICT(prog->edicts);
1310 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1312 prog->xfunction->builtinsprofile++;
1313 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1317 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1318 continue; // don't aim at teammate
1319 for (j=0 ; j<3 ; j++)
1320 end[j] = PRVM_serveredictvector(check, origin)[j]
1321 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1322 VectorSubtract (end, start, dir);
1323 VectorNormalize (dir);
1324 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1325 if (dist < bestdist)
1326 continue; // to far to turn
1327 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1328 if (tr.ent == check)
1329 { // can shoot at this one
1337 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1338 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1339 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1341 VectorNormalize (end);
1342 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1346 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1351 ===============================================================================
1355 ===============================================================================
1358 #define MSG_BROADCAST 0 // unreliable to all
1359 #define MSG_ONE 1 // reliable to one (msg_entity)
1360 #define MSG_ALL 2 // reliable to all
1361 #define MSG_INIT 3 // write to the init string
1362 #define MSG_ENTITY 5
1364 sizebuf_t *WriteDest (void)
1370 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1374 return &sv.datagram;
1377 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1378 entnum = PRVM_NUM_FOR_EDICT(ent);
1379 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1381 VM_Warning ("WriteDest: tried to write to non-client\n");
1382 return &sv.reliable_datagram;
1385 return &svs.clients[entnum-1].netconnection->message;
1388 VM_Warning ("WriteDest: bad destination\n");
1390 return &sv.reliable_datagram;
1396 return sv.writeentitiestoclient_msg;
1402 static void VM_SV_WriteByte (void)
1404 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1405 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1408 static void VM_SV_WriteChar (void)
1410 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1411 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1414 static void VM_SV_WriteShort (void)
1416 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1417 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1420 static void VM_SV_WriteLong (void)
1422 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1423 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1426 static void VM_SV_WriteAngle (void)
1428 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1429 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1432 static void VM_SV_WriteCoord (void)
1434 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1435 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1438 static void VM_SV_WriteString (void)
1440 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1441 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1444 static void VM_SV_WriteUnterminatedString (void)
1446 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1447 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1451 static void VM_SV_WriteEntity (void)
1453 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1454 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1457 // writes a picture as at most size bytes of data
1459 // IMGNAME \0 SIZE(short) IMGDATA
1460 // if failed to read/compress:
1462 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1463 static void VM_SV_WritePicture (void)
1465 const char *imgname;
1469 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1471 imgname = PRVM_G_STRING(OFS_PARM1);
1472 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1476 MSG_WriteString(WriteDest(), imgname);
1477 if(Image_Compress(imgname, size, &buf, &size))
1480 MSG_WriteShort(WriteDest(), size);
1481 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1486 MSG_WriteShort(WriteDest(), 0);
1490 //////////////////////////////////////////////////////////
1492 static void VM_SV_makestatic (void)
1497 // allow 0 parameters due to an id1 qc bug in which this function is used
1498 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1499 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1501 if (prog->argc >= 1)
1502 ent = PRVM_G_EDICT(OFS_PARM0);
1504 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1505 if (ent == prog->edicts)
1507 VM_Warning("makestatic: can not modify world entity\n");
1510 if (ent->priv.server->free)
1512 VM_Warning("makestatic: can not modify free entity\n");
1517 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1522 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1523 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1524 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1526 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1528 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1529 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1530 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1534 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1535 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1536 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1539 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1540 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1541 for (i=0 ; i<3 ; i++)
1543 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1544 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1547 // throw the entity away now
1551 //=============================================================================
1558 static void VM_SV_setspawnparms (void)
1564 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1566 ent = PRVM_G_EDICT(OFS_PARM0);
1567 i = PRVM_NUM_FOR_EDICT(ent);
1568 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1570 Con_Print("tried to setspawnparms on a non-client\n");
1574 // copy spawn parms out of the client_t
1575 client = svs.clients + i-1;
1576 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1577 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1584 Returns a color vector indicating the lighting at the requested point.
1586 (Internal Operation note: actually measures the light beneath the point, just like
1587 the model lighting on the client)
1592 static void VM_SV_getlight (void)
1594 vec3_t ambientcolor, diffusecolor, diffusenormal;
1596 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1597 p = PRVM_G_VECTOR(OFS_PARM0);
1598 VectorClear(ambientcolor);
1599 VectorClear(diffusecolor);
1600 VectorClear(diffusenormal);
1601 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1602 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1603 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1608 unsigned char type; // 1/2/8 or other value if isn't used
1612 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1613 static int vm_customstats_last;
1615 void VM_CustomStats_Clear (void)
1619 Z_Free(vm_customstats);
1620 vm_customstats = NULL;
1621 vm_customstats_last = -1;
1625 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1633 for(i=0; i<vm_customstats_last+1 ;i++)
1635 if(!vm_customstats[i].type)
1637 switch(vm_customstats[i].type)
1639 //string as 16 bytes
1642 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1643 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1644 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1645 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1646 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1648 //float field sent as-is
1650 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1652 //integer value of float field
1654 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1662 // void(float index, float type, .void field) SV_AddStat = #232;
1663 // Set up an auto-sent player stat.
1664 // Client's get thier own fields sent to them. Index may not be less than 32.
1665 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1666 // 1: string (4 stats carrying a total of 16 charactures)
1667 // 2: float (one stat, float converted to an integer for transportation)
1668 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1669 static void VM_SV_AddStat (void)
1674 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1678 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1681 VM_Warning("PF_SV_AddStat: not enough memory\n");
1685 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1686 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1687 off = PRVM_G_INT (OFS_PARM2);
1692 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1695 if(i >= (MAX_CL_STATS-32))
1697 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1700 if(i > (MAX_CL_STATS-32-4) && type == 1)
1702 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1705 vm_customstats[i].type = type;
1706 vm_customstats[i].fieldoffset = off;
1707 if(vm_customstats_last < i)
1708 vm_customstats_last = i;
1715 copies data from one entity to another
1717 copyentity(src, dst)
1720 static void VM_SV_copyentity (void)
1722 prvm_edict_t *in, *out;
1723 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1724 in = PRVM_G_EDICT(OFS_PARM0);
1725 if (in == prog->edicts)
1727 VM_Warning("copyentity: can not read world entity\n");
1730 if (in->priv.server->free)
1732 VM_Warning("copyentity: can not read free entity\n");
1735 out = PRVM_G_EDICT(OFS_PARM1);
1736 if (out == prog->edicts)
1738 VM_Warning("copyentity: can not modify world entity\n");
1741 if (out->priv.server->free)
1743 VM_Warning("copyentity: can not modify free entity\n");
1746 memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
1755 sets the color of a client and broadcasts the update to all connected clients
1757 setcolor(clientent, value)
1760 static void VM_SV_setcolor (void)
1765 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1766 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1767 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1769 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1771 Con_Print("tried to setcolor a non-client\n");
1775 client = svs.clients + entnum-1;
1778 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1779 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1782 if (client->old_colors != client->colors)
1784 client->old_colors = client->colors;
1785 // send notification to all clients
1786 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1787 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1788 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1796 effect(origin, modelname, startframe, framecount, framerate)
1799 static void VM_SV_effect (void)
1803 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1804 s = PRVM_G_STRING(OFS_PARM1);
1807 VM_Warning("effect: no model specified\n");
1811 i = SV_ModelIndex(s, 1);
1814 VM_Warning("effect: model not precached\n");
1818 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1820 VM_Warning("effect: framecount < 1\n");
1824 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1826 VM_Warning("effect: framerate < 1\n");
1830 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));
1833 static void VM_SV_te_blood (void)
1835 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1836 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1838 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1839 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1841 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1842 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1843 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1845 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1846 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1847 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1849 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1850 SV_FlushBroadcastMessages();
1853 static void VM_SV_te_bloodshower (void)
1855 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1856 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1858 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1859 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1861 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1862 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1863 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1865 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1866 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1869 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1871 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1872 SV_FlushBroadcastMessages();
1875 static void VM_SV_te_explosionrgb (void)
1877 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1878 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1879 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1881 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1882 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1883 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1885 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1886 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1887 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1888 SV_FlushBroadcastMessages();
1891 static void VM_SV_te_particlecube (void)
1893 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1894 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1896 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1897 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1900 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1911 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1913 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1914 // gravity true/false
1915 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1917 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1918 SV_FlushBroadcastMessages();
1921 static void VM_SV_te_particlerain (void)
1923 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1924 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1926 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1927 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1934 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1941 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1943 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1944 SV_FlushBroadcastMessages();
1947 static void VM_SV_te_particlesnow (void)
1949 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1950 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1952 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1953 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1955 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1964 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1965 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1967 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1969 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1970 SV_FlushBroadcastMessages();
1973 static void VM_SV_te_spark (void)
1975 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1976 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1978 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1979 MSG_WriteByte(&sv.datagram, TE_SPARK);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1983 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1985 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1986 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1987 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1989 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1990 SV_FlushBroadcastMessages();
1993 static void VM_SV_te_gunshotquad (void)
1995 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1996 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1997 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1999 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2000 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2001 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2002 SV_FlushBroadcastMessages();
2005 static void VM_SV_te_spikequad (void)
2007 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2008 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2009 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2011 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2012 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2014 SV_FlushBroadcastMessages();
2017 static void VM_SV_te_superspikequad (void)
2019 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2020 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2021 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2023 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2024 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2025 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2026 SV_FlushBroadcastMessages();
2029 static void VM_SV_te_explosionquad (void)
2031 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2032 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2033 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2035 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2036 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2037 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2038 SV_FlushBroadcastMessages();
2041 static void VM_SV_te_smallflash (void)
2043 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2044 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2045 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2047 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2048 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2049 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2050 SV_FlushBroadcastMessages();
2053 static void VM_SV_te_customflash (void)
2055 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2056 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2058 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2059 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2061 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2062 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2063 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2065 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2067 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2069 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2070 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2071 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2072 SV_FlushBroadcastMessages();
2075 static void VM_SV_te_gunshot (void)
2077 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2078 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2079 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2081 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2082 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2083 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2084 SV_FlushBroadcastMessages();
2087 static void VM_SV_te_spike (void)
2089 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2090 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2091 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2093 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2094 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2095 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2096 SV_FlushBroadcastMessages();
2099 static void VM_SV_te_superspike (void)
2101 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2102 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2103 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2105 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2106 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2107 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2108 SV_FlushBroadcastMessages();
2111 static void VM_SV_te_explosion (void)
2113 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2114 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2115 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2117 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2118 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2119 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2120 SV_FlushBroadcastMessages();
2123 static void VM_SV_te_tarexplosion (void)
2125 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2126 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2127 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2129 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2130 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2131 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2132 SV_FlushBroadcastMessages();
2135 static void VM_SV_te_wizspike (void)
2137 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2138 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2139 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2141 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2142 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2143 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2144 SV_FlushBroadcastMessages();
2147 static void VM_SV_te_knightspike (void)
2149 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2150 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2151 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2153 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2154 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2155 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2156 SV_FlushBroadcastMessages();
2159 static void VM_SV_te_lavasplash (void)
2161 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2162 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2163 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2165 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2166 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2167 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2168 SV_FlushBroadcastMessages();
2171 static void VM_SV_te_teleport (void)
2173 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2174 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2175 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2177 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2178 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2179 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2180 SV_FlushBroadcastMessages();
2183 static void VM_SV_te_explosion2 (void)
2185 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2186 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2187 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2189 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2190 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2191 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2193 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2194 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2195 SV_FlushBroadcastMessages();
2198 static void VM_SV_te_lightning1 (void)
2200 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2201 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2202 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2204 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2206 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2207 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2208 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2210 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2211 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2212 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2213 SV_FlushBroadcastMessages();
2216 static void VM_SV_te_lightning2 (void)
2218 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2219 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2220 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2222 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2224 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2225 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2226 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2230 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2231 SV_FlushBroadcastMessages();
2234 static void VM_SV_te_lightning3 (void)
2236 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2237 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2238 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2240 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2242 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2243 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2244 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2246 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2247 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2248 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2249 SV_FlushBroadcastMessages();
2252 static void VM_SV_te_beam (void)
2254 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2255 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2256 MSG_WriteByte(&sv.datagram, TE_BEAM);
2258 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2260 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2261 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2262 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2264 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2265 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2266 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2267 SV_FlushBroadcastMessages();
2270 static void VM_SV_te_plasmaburn (void)
2272 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2273 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2274 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2275 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2276 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2277 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2278 SV_FlushBroadcastMessages();
2281 static void VM_SV_te_flamejet (void)
2283 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2284 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2285 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2287 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2288 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2289 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2291 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2292 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2293 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2295 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2296 SV_FlushBroadcastMessages();
2299 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2300 //this function originally written by KrimZon, made shorter by LordHavoc
2301 static void VM_SV_clientcommand (void)
2303 client_t *temp_client;
2305 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2307 //find client for this entity
2308 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2309 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2311 Con_Print("PF_clientcommand: entity is not a client\n");
2315 temp_client = host_client;
2316 host_client = svs.clients + i;
2317 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2318 host_client = temp_client;
2321 //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)
2322 static void VM_SV_setattachment (void)
2324 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2325 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2326 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2329 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2331 if (e == prog->edicts)
2333 VM_Warning("setattachment: can not modify world entity\n");
2336 if (e->priv.server->free)
2338 VM_Warning("setattachment: can not modify free entity\n");
2342 if (tagentity == NULL)
2343 tagentity = prog->edicts;
2347 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2349 model = SV_GetModelFromEdict(tagentity);
2352 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2354 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);
2357 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));
2360 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2361 PRVM_serveredictfloat(e, tag_index) = tagindex;
2364 /////////////////////////////////////////
2365 // DP_MD3_TAGINFO extension coded by VorteX
2367 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2371 i = (int)PRVM_serveredictfloat(e, modelindex);
2372 if (i < 1 || i >= MAX_MODELS)
2375 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2378 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2385 Matrix4x4_CreateIdentity(tag_localmatrix);
2387 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2389 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2400 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2403 float pitchsign = 1;
2405 scale = PRVM_serveredictfloat(ent, scale);
2410 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);
2413 pitchsign = SV_GetPitchSign(ent);
2414 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);
2418 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2421 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2423 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2424 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2425 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2426 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2428 *out = identitymatrix;
2432 // Warnings/errors code:
2433 // 0 - normal (everything all-right)
2436 // 3 - null or non-precached model
2437 // 4 - no tags with requested index
2438 // 5 - runaway loop at attachment chain
2439 extern cvar_t cl_bob;
2440 extern cvar_t cl_bobcycle;
2441 extern cvar_t cl_bobup;
2442 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2445 int modelindex, attachloop;
2446 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2449 *out = identitymatrix; // warnings and errors return identical matrix
2451 if (ent == prog->edicts)
2453 if (ent->priv.server->free)
2456 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2457 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2460 model = SV_GetModelByIndex(modelindex);
2462 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2463 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2464 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2466 tagmatrix = identitymatrix;
2467 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2471 if (attachloop >= 256) // prevent runaway looping
2473 // apply transformation by child's tagindex on parent entity and then
2474 // by parent entity itself
2475 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2476 if (ret && attachloop == 0)
2478 SV_GetEntityMatrix(ent, &entitymatrix, false);
2479 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2480 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2481 // next iteration we process the parent entity
2482 if (PRVM_serveredictedict(ent, tag_entity))
2484 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2485 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2492 // RENDER_VIEWMODEL magic
2493 if (PRVM_serveredictedict(ent, viewmodelforclient))
2495 Matrix4x4_Copy(&tagmatrix, out);
2496 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2498 SV_GetEntityMatrix(ent, &entitymatrix, true);
2499 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2502 // Cl_bob, ported from rendering code
2503 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2506 // LordHavoc: this code is *weird*, but not replacable (I think it
2507 // should be done in QC on the server, but oh well, quake is quake)
2508 // LordHavoc: figured out bobup: the time at which the sin is at 180
2509 // degrees (which allows lengthening or squishing the peak or valley)
2510 cycle = sv.time/cl_bobcycle.value;
2511 cycle -= (int)cycle;
2512 if (cycle < cl_bobup.value)
2513 cycle = sin(M_PI * cycle / cl_bobup.value);
2515 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2516 // bob is proportional to velocity in the xy plane
2517 // (don't count Z, or jumping messes it up)
2518 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;
2519 bob = bob*0.3 + bob*0.7*cycle;
2520 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2527 //float(entity ent, string tagname) gettagindex;
2529 static void VM_SV_gettagindex (void)
2532 const char *tag_name;
2535 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2537 ent = PRVM_G_EDICT(OFS_PARM0);
2538 tag_name = PRVM_G_STRING(OFS_PARM1);
2540 if (ent == prog->edicts)
2542 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2545 if (ent->priv.server->free)
2547 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2552 if (!SV_GetModelFromEdict(ent))
2553 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2556 tag_index = SV_GetTagIndex(ent, tag_name);
2558 if(developer_extra.integer)
2559 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2561 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2564 //vector(entity ent, float tagindex) gettaginfo;
2565 static void VM_SV_gettaginfo (void)
2569 matrix4x4_t tag_matrix;
2570 matrix4x4_t tag_localmatrix;
2572 const char *tagname;
2574 vec3_t fo, le, up, trans;
2575 const dp_model_t *model;
2577 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2579 e = PRVM_G_EDICT(OFS_PARM0);
2580 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2582 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2583 Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
2584 VectorScale(le, -1, PRVM_serverglobalvector(v_right));
2585 model = SV_GetModelFromEdict(e);
2586 VM_GenerateFrameGroupBlend(e->priv.server->framegroupblend, e);
2587 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
2588 VM_UpdateEdictSkeleton(e, model, e->priv.server->frameblend);
2589 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2590 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2592 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2593 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(tagname) : 0;
2594 VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
2595 VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
2596 VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
2597 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2602 VM_Warning("gettagindex: can't affect world entity\n");
2605 VM_Warning("gettagindex: can't affect free entity\n");
2608 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2611 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2614 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2619 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2620 static void VM_SV_dropclient (void)
2623 client_t *oldhostclient;
2624 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2625 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2626 if (clientnum < 0 || clientnum >= svs.maxclients)
2628 VM_Warning("dropclient: not a client\n");
2631 if (!svs.clients[clientnum].active)
2633 VM_Warning("dropclient: that client slot is not connected\n");
2636 oldhostclient = host_client;
2637 host_client = svs.clients + clientnum;
2638 SV_DropClient(false);
2639 host_client = oldhostclient;
2642 //entity() spawnclient (DP_SV_BOTCLIENT)
2643 static void VM_SV_spawnclient (void)
2647 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2648 prog->xfunction->builtinsprofile += 2;
2650 for (i = 0;i < svs.maxclients;i++)
2652 if (!svs.clients[i].active)
2654 prog->xfunction->builtinsprofile += 100;
2655 SV_ConnectClient (i, NULL);
2656 // this has to be set or else ClientDisconnect won't be called
2657 // we assume the qc will call ClientConnect...
2658 svs.clients[i].clientconnectcalled = true;
2659 ed = PRVM_EDICT_NUM(i + 1);
2663 VM_RETURN_EDICT(ed);
2666 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2667 static void VM_SV_clienttype (void)
2670 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2671 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2672 if (clientnum < 0 || clientnum >= svs.maxclients)
2673 PRVM_G_FLOAT(OFS_RETURN) = 3;
2674 else if (!svs.clients[clientnum].active)
2675 PRVM_G_FLOAT(OFS_RETURN) = 0;
2676 else if (svs.clients[clientnum].netconnection)
2677 PRVM_G_FLOAT(OFS_RETURN) = 1;
2679 PRVM_G_FLOAT(OFS_RETURN) = 2;
2686 string(string key) serverkey
2689 void VM_SV_serverkey(void)
2691 char string[VM_STRINGTEMP_LENGTH];
2692 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2693 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2694 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2697 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2698 static void VM_SV_setmodelindex (void)
2703 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2705 e = PRVM_G_EDICT(OFS_PARM0);
2706 if (e == prog->edicts)
2708 VM_Warning("setmodelindex: can not modify world entity\n");
2711 if (e->priv.server->free)
2713 VM_Warning("setmodelindex: can not modify free entity\n");
2716 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2717 if (i <= 0 || i >= MAX_MODELS)
2719 VM_Warning("setmodelindex: invalid modelindex\n");
2722 if (!sv.model_precache[i][0])
2724 VM_Warning("setmodelindex: model not precached\n");
2728 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
2729 PRVM_serveredictfloat(e, modelindex) = i;
2731 mod = SV_GetModelByIndex(i);
2735 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2736 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2738 SetMinMaxSize (e, quakemins, quakemaxs, true);
2741 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2744 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2745 static void VM_SV_modelnameforindex (void)
2748 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2750 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2752 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2753 if (i <= 0 || i >= MAX_MODELS)
2755 VM_Warning("modelnameforindex: invalid modelindex\n");
2758 if (!sv.model_precache[i][0])
2760 VM_Warning("modelnameforindex: model not precached\n");
2764 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2767 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2768 static void VM_SV_particleeffectnum (void)
2771 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2772 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2775 PRVM_G_FLOAT(OFS_RETURN) = i;
2778 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2779 static void VM_SV_trailparticles (void)
2781 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2783 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2786 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2787 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2788 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2789 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2790 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2791 SV_FlushBroadcastMessages();
2794 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2795 static void VM_SV_pointparticles (void)
2797 int effectnum, count;
2799 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2801 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2804 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2805 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2806 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2807 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2808 if (count == 1 && !VectorLength2(vel))
2811 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2812 MSG_WriteShort(&sv.datagram, effectnum);
2813 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2817 // 1+2+12+12+2=29 bytes
2818 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2819 MSG_WriteShort(&sv.datagram, effectnum);
2820 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2821 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2822 MSG_WriteShort(&sv.datagram, count);
2825 SV_FlushBroadcastMessages();
2828 //PF_setpause, // void(float pause) setpause = #531;
2829 static void VM_SV_setpause(void) {
2831 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2832 if (pauseValue != 0) { //pause the game
2834 sv.pausedstart = Sys_DoubleTime();
2835 } else { //disable pause, in case it was enabled
2836 if (sv.paused != 0) {
2841 // send notification to all clients
2842 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2843 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2846 // #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.
2847 static void VM_SV_skel_create(void)
2849 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2850 dp_model_t *model = SV_GetModelByIndex(modelindex);
2851 skeleton_t *skeleton;
2853 PRVM_G_FLOAT(OFS_RETURN) = 0;
2854 if (!model || !model->num_bones)
2856 for (i = 0;i < MAX_EDICTS;i++)
2857 if (!prog->skeletons[i])
2859 if (i == MAX_EDICTS)
2861 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2862 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2863 skeleton->model = model;
2864 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2865 // initialize to identity matrices
2866 for (i = 0;i < skeleton->model->num_bones;i++)
2867 skeleton->relativetransforms[i] = identitymatrix;
2870 // #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
2871 static void VM_SV_skel_build(void)
2873 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2874 skeleton_t *skeleton;
2875 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2876 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2877 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2878 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2879 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2880 dp_model_t *model = SV_GetModelByIndex(modelindex);
2885 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2886 frameblend_t frameblend[MAX_FRAMEBLENDS];
2887 matrix4x4_t blendedmatrix;
2889 PRVM_G_FLOAT(OFS_RETURN) = 0;
2890 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2892 firstbone = max(0, firstbone);
2893 lastbone = min(lastbone, model->num_bones - 1);
2894 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2895 VM_GenerateFrameGroupBlend(framegroupblend, ed);
2896 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
2897 blendfrac = 1.0f - retainfrac;
2898 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2899 frameblend[numblends].lerp *= blendfrac;
2900 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2902 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2903 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2904 for (blendindex = 0;blendindex < numblends;blendindex++)
2906 Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2907 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2909 skeleton->relativetransforms[bonenum] = blendedmatrix;
2911 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2914 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2915 static void VM_SV_skel_get_numbones(void)
2917 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2918 skeleton_t *skeleton;
2919 PRVM_G_FLOAT(OFS_RETURN) = 0;
2920 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2922 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2925 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2926 static void VM_SV_skel_get_bonename(void)
2928 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2929 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2930 skeleton_t *skeleton;
2931 PRVM_G_INT(OFS_RETURN) = 0;
2932 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2934 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2936 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(skeleton->model->data_bones[bonenum].name);
2939 // #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)
2940 static void VM_SV_skel_get_boneparent(void)
2942 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2943 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2944 skeleton_t *skeleton;
2945 PRVM_G_FLOAT(OFS_RETURN) = 0;
2946 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2948 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2950 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2953 // #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
2954 static void VM_SV_skel_find_bone(void)
2956 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2957 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2958 skeleton_t *skeleton;
2959 PRVM_G_FLOAT(OFS_RETURN) = 0;
2960 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2962 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2965 // #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)
2966 static void VM_SV_skel_get_bonerel(void)
2968 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2969 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2970 skeleton_t *skeleton;
2972 vec3_t forward, left, up, origin;
2973 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2974 VectorClear(PRVM_clientglobalvector(v_forward));
2975 VectorClear(PRVM_clientglobalvector(v_right));
2976 VectorClear(PRVM_clientglobalvector(v_up));
2977 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2979 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2981 matrix = skeleton->relativetransforms[bonenum];
2982 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2983 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2984 VectorNegate(left, PRVM_clientglobalvector(v_right));
2985 VectorCopy(up, PRVM_clientglobalvector(v_up));
2986 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2989 // #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)
2990 static void VM_SV_skel_get_boneabs(void)
2992 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2993 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2994 skeleton_t *skeleton;
2997 vec3_t forward, left, up, origin;
2998 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2999 VectorClear(PRVM_clientglobalvector(v_forward));
3000 VectorClear(PRVM_clientglobalvector(v_right));
3001 VectorClear(PRVM_clientglobalvector(v_up));
3002 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3004 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3006 matrix = skeleton->relativetransforms[bonenum];
3007 // convert to absolute
3008 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3011 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3013 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3014 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3015 VectorNegate(left, PRVM_clientglobalvector(v_right));
3016 VectorCopy(up, PRVM_clientglobalvector(v_up));
3017 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3020 // #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)
3021 static void VM_SV_skel_set_bone(void)
3023 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3024 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3025 vec3_t forward, left, up, origin;
3026 skeleton_t *skeleton;
3028 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3030 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3032 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3033 VectorNegate(PRVM_clientglobalvector(v_right), left);
3034 VectorCopy(PRVM_clientglobalvector(v_up), up);
3035 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3036 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3037 skeleton->relativetransforms[bonenum] = matrix;
3040 // #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)
3041 static void VM_SV_skel_mul_bone(void)
3043 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3044 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3045 vec3_t forward, left, up, origin;
3046 skeleton_t *skeleton;
3049 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3051 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3053 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3054 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3055 VectorNegate(PRVM_clientglobalvector(v_right), left);
3056 VectorCopy(PRVM_clientglobalvector(v_up), up);
3057 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3058 temp = skeleton->relativetransforms[bonenum];
3059 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3062 // #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)
3063 static void VM_SV_skel_mul_bones(void)
3065 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3066 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3067 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3069 vec3_t forward, left, up, origin;
3070 skeleton_t *skeleton;
3073 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3075 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3076 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3077 VectorNegate(PRVM_clientglobalvector(v_right), left);
3078 VectorCopy(PRVM_clientglobalvector(v_up), up);
3079 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3080 firstbone = max(0, firstbone);
3081 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3082 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3084 temp = skeleton->relativetransforms[bonenum];
3085 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3089 // #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
3090 static void VM_SV_skel_copybones(void)
3092 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3093 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3094 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3095 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3097 skeleton_t *skeletondst;
3098 skeleton_t *skeletonsrc;
3099 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3101 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3103 firstbone = max(0, firstbone);
3104 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3105 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3106 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3107 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3110 // #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)
3111 static void VM_SV_skel_delete(void)
3113 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3114 skeleton_t *skeleton;
3115 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3118 prog->skeletons[skeletonindex] = NULL;
3121 // #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
3122 static void VM_SV_frameforname(void)
3124 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3125 dp_model_t *model = SV_GetModelByIndex(modelindex);
3126 const char *name = PRVM_G_STRING(OFS_PARM1);
3128 PRVM_G_FLOAT(OFS_RETURN) = -1;
3129 if (!model || !model->animscenes)
3131 for (i = 0;i < model->numframes;i++)
3133 if (!strcasecmp(model->animscenes[i].name, name))
3135 PRVM_G_FLOAT(OFS_RETURN) = i;
3141 // #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.
3142 static void VM_SV_frameduration(void)
3144 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3145 dp_model_t *model = SV_GetModelByIndex(modelindex);
3146 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3147 PRVM_G_FLOAT(OFS_RETURN) = 0;
3148 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3150 if (model->animscenes[framenum].framerate)
3151 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3155 prvm_builtin_t vm_sv_builtins[] = {
3156 NULL, // #0 NULL function (not callable) (QUAKE)
3157 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3158 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3159 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3160 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3161 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3162 VM_break, // #6 void() break (QUAKE)
3163 VM_random, // #7 float() random (QUAKE)
3164 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3165 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3166 VM_error, // #10 void(string e) error (QUAKE)
3167 VM_objerror, // #11 void(string e) objerror (QUAKE)
3168 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3169 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3170 VM_spawn, // #14 entity() spawn (QUAKE)
3171 VM_remove, // #15 void(entity e) remove (QUAKE)
3172 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3173 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3174 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3175 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3176 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3177 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3178 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3179 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3180 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3181 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3182 VM_ftos, // #26 string(float f) ftos (QUAKE)
3183 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3184 VM_coredump, // #28 void() coredump (QUAKE)
3185 VM_traceon, // #29 void() traceon (QUAKE)
3186 VM_traceoff, // #30 void() traceoff (QUAKE)
3187 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3188 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3189 NULL, // #33 (QUAKE)
3190 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3191 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3192 VM_rint, // #36 float(float v) rint (QUAKE)
3193 VM_floor, // #37 float(float v) floor (QUAKE)
3194 VM_ceil, // #38 float(float v) ceil (QUAKE)
3195 NULL, // #39 (QUAKE)
3196 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3197 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3198 NULL, // #42 (QUAKE)
3199 VM_fabs, // #43 float(float f) fabs (QUAKE)
3200 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3201 VM_cvar, // #45 float(string s) cvar (QUAKE)
3202 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3203 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3204 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3205 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3206 NULL, // #50 (QUAKE)
3207 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3208 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3209 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3210 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3211 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3212 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3213 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3214 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3215 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3216 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3217 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3218 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3219 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3220 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3221 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3222 NULL, // #66 (QUAKE)
3223 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3224 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3225 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3226 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3227 NULL, // #71 (QUAKE)
3228 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3229 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3230 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3231 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3232 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3233 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3234 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3235 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3236 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3237 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3238 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3239 NULL, // #83 (QUAKE)
3240 NULL, // #84 (QUAKE)
3241 NULL, // #85 (QUAKE)
3242 NULL, // #86 (QUAKE)
3243 NULL, // #87 (QUAKE)
3244 NULL, // #88 (QUAKE)
3245 NULL, // #89 (QUAKE)
3246 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3247 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3248 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3249 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3250 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3251 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3252 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3253 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3254 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3255 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3256 // FrikaC and Telejano range #100-#199
3267 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3268 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3269 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3270 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3271 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3272 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3273 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3274 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3275 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3276 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3357 // FTEQW range #200-#299
3376 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3379 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3380 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3381 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3382 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3383 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3384 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3385 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3386 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3387 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3388 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3390 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3398 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3421 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.
3422 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
3423 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3424 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3425 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)
3426 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
3427 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)
3428 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)
3429 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)
3430 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)
3431 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)
3432 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
3433 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)
3434 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
3435 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.
3458 // CSQC range #300-#399
3459 NULL, // #300 void() clearscene (EXT_CSQC)
3460 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3461 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3462 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3463 NULL, // #304 void() renderscene (EXT_CSQC)
3464 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3465 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3466 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3467 NULL, // #308 void() R_EndPolygon
3469 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3470 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3474 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3475 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3476 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3477 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3478 NULL, // #319 void(string name) freepic (EXT_CSQC)
3479 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3480 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3481 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3482 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3483 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3484 NULL, // #325 void(void) drawresetcliparea
3489 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3490 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3491 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3492 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3493 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3494 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3495 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3496 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3497 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3498 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3499 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3500 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3501 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3502 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3503 NULL, // #344 vector() getmousepos (EXT_CSQC)
3504 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3505 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3506 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3507 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3508 NULL, // #349 float() isdemo (EXT_CSQC)
3509 VM_isserver, // #350 float() isserver (EXT_CSQC)
3510 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3511 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3512 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3513 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3519 NULL, // #360 float() readbyte (EXT_CSQC)
3520 NULL, // #361 float() readchar (EXT_CSQC)
3521 NULL, // #362 float() readshort (EXT_CSQC)
3522 NULL, // #363 float() readlong (EXT_CSQC)
3523 NULL, // #364 float() readcoord (EXT_CSQC)
3524 NULL, // #365 float() readangle (EXT_CSQC)
3525 NULL, // #366 string() readstring (EXT_CSQC)
3526 NULL, // #367 float() readfloat (EXT_CSQC)
3559 // LordHavoc's range #400-#499
3560 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3561 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3562 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3563 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3564 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3565 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3566 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3567 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3568 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)
3569 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3570 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3571 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3572 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3573 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3574 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3575 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3576 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3577 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3578 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3579 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3580 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3581 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3582 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3583 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3584 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3585 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3586 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3587 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3588 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3589 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3590 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3591 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3592 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3593 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3594 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3595 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3596 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3597 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3598 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3599 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3600 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3601 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3602 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3603 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3604 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3605 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3606 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3607 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3608 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3609 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3610 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3611 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3612 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3613 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3614 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3615 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3616 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3617 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3619 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3620 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3621 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3622 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3623 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3624 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3625 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3626 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3627 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3628 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3629 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3631 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3632 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3633 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3634 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3635 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3636 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3637 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3638 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3639 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3640 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3641 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3642 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3643 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3644 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3645 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3646 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3654 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3655 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3656 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3657 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3658 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3659 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3660 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3661 VM_SV_WritePicture, // #501
3663 VM_whichpack, // #503 string(string) whichpack = #503;
3670 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3671 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3672 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3673 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)
3674 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3675 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3676 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3677 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3678 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3679 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3689 VM_loadfromdata, // #529
3690 VM_loadfromfile, // #530
3691 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3693 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3694 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3700 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3701 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3702 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3765 VM_callfunction, // #605
3766 VM_writetofile, // #606
3767 VM_isfunction, // #607
3773 VM_parseentitydata, // #613
3784 VM_SV_getextresponse, // #624 string getextresponse(void)
3787 VM_sprintf, // #627 string sprintf(string format, ...)
3788 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3789 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3793 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3795 void VM_SV_Cmd_Init(void)
3800 void VM_SV_Cmd_Reset(void)
3802 World_End(&sv.world);
3803 if(PRVM_serverfunction(SV_Shutdown))
3805 func_t s = PRVM_serverfunction(SV_Shutdown);
3806 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3807 PRVM_ExecuteProgram(s,"SV_Shutdown() required");