6 //============================================================================
11 const char *vm_sv_extensions[] = {
16 "DP_CON_ALIASPARAMETERS",
25 "DP_CSQC_ENTITYWORLDOBJECT",
26 "DP_CSQC_ENTITYMODELLIGHT",
27 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET",
29 "DP_CSQC_MINFPS_QUALITY",
30 "DP_CSQC_MULTIFRAME_INTERPOLATION",
31 "DP_CSQC_BOXPARTICLES",
32 "DP_CSQC_SPAWNPARTICLE",
33 "DP_CSQC_QUERYRENDERENTITY",
34 "DP_CSQC_ROTATEMOVES",
36 "DP_CSQC_V_CALCREFDEF_WIP1",
37 "DP_CSQC_V_CALCREFDEF_WIP2",
41 "DP_EF_DYNAMICMODELLIGHT",
50 "DP_EF_RESTARTANIM_BIT",
55 "DP_ENT_CUSTOMCOLORMAP",
56 "DP_ENT_EXTERIORMODELTOCLIENT",
59 "DP_ENT_LOWPRECISION",
61 "DP_ENT_TRAILEFFECTNUM",
63 "DP_GFX_EXTERNALTEXTURES",
64 "DP_GFX_EXTERNALTEXTURES_PERMAP",
66 "DP_GFX_MODEL_INTERPOLATION",
67 "DP_GFX_QUAKE3MODELTAGS",
71 "DP_GFX_FONTS_FREETYPE",
73 "DP_FONT_VARIABLEWIDTH",
75 "DP_HALFLIFE_MAP_CVAR",
78 "DP_LIGHTSTYLE_STATICVALUE",
82 "DP_MOVETYPEBOUNCEMISSILE",
83 "DP_MOVETYPEFLYWORLDONLY",
86 "DP_QC_ASINACOSATANATAN2TAN",
92 "DP_QC_CVAR_DEFSTRING",
93 "DP_QC_CVAR_DESCRIPTION",
97 "DP_QC_DIGEST_SHA256",
100 "DP_QC_ENTITYSTRING",
102 "DP_QC_EXTRESPONSEPACKET",
105 "DP_QC_FINDCHAINFLAGS",
106 "DP_QC_FINDCHAINFLOAT",
107 "DP_QC_FINDCHAIN_TOFIELD",
111 "DP_QC_FS_SEARCH_PACKFILE",
114 "DP_QC_GETSURFACETRIANGLE",
115 "DP_QC_GETSURFACEPOINTATTRIBUTE",
117 "DP_QC_GETTAGINFO_BONEPROPERTIES",
119 "DP_QC_GETTIME_CDTRACK",
123 "DP_QC_MULTIPLETEMPSTRINGS",
124 "DP_QC_NUDGEOUTOFSOLID",
125 "DP_QC_NUM_FOR_EDICT",
127 "DP_QC_SINCOSSQRTPOW",
130 "DP_QC_STRINGBUFFERS",
131 "DP_QC_STRINGBUFFERS_CVARLIST",
132 "DP_QC_STRINGBUFFERS_EXT_WIP",
133 "DP_QC_STRINGCOLORFUNCTIONS",
134 "DP_QC_STRING_CASE_FUNCTIONS",
136 "DP_QC_TOKENIZEBYSEPARATOR",
137 "DP_QC_TOKENIZE_CONSOLE",
140 "DP_QC_TRACE_MOVETYPE_HITMODEL",
141 "DP_QC_TRACE_MOVETYPE_WORLDONLY",
142 "DP_QC_UNLIMITEDTEMPSTRINGS",
146 "DP_QC_VECTOANGLES_WITH_ROLL",
147 "DP_QC_VECTORVECTORS",
154 "DP_SKELETONOBJECTS",
155 "DP_SND_DIRECTIONLESSATTNNONE",
157 "DP_SND_SOUND7_WIP1",
158 "DP_SND_SOUND7_WIP2",
162 "DP_SND_GETSOUNDTIME",
164 "DP_VIDEO_SUBTITLES",
168 "DP_SV_BOUNCEFACTOR",
169 "DP_SV_CLIENTCAMERA",
170 "DP_SV_CLIENTCOLORS",
173 "DP_SV_CUSTOMIZEENTITYFORCLIENT",
174 "DP_SV_DISABLECLIENTPREDICTION",
175 "DP_SV_DISCARDABLEDEMO",
176 "DP_SV_DRAWONLYTOCLIENT",
179 "DP_SV_ENTITYCONTENTSTRANSITION",
180 "DP_SV_MODELFLAGS_AS_EFFECTS",
181 "DP_SV_MOVETYPESTEP_LANDEVENT",
183 "DP_SV_NODRAWTOCLIENT",
184 "DP_SV_ONENTITYNOSPAWNFUNCTION",
185 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION",
187 "DP_SV_PING_PACKETLOSS",
188 "DP_SV_PLAYERPHYSICS",
190 "DP_SV_POINTPARTICLES",
192 "DP_SV_PRECACHEANYTIME",
196 "DP_SV_ROTATINGBMODEL",
200 "DP_SV_SPAWNFUNC_PREFIX",
201 "DP_SV_WRITEPICTURE",
202 "DP_SV_WRITEUNTERMINATEDSTRING",
206 "DP_TE_EXPLOSIONRGB",
208 "DP_TE_PARTICLECUBE",
209 "DP_TE_PARTICLERAIN",
210 "DP_TE_PARTICLESNOW",
212 "DP_TE_QUADEFFECTS1",
215 "DP_TE_STANDARDEFFECTBUILTINS",
216 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO"
221 "FTE_CSQC_SKELETONOBJECTS",
224 "KRIMZON_SV_PARSECLIENTCOMMAND",
227 "NEXUIZ_PLAYERMODEL",
229 "PRYDON_CLIENTCURSOR",
230 "TENEBRAE_GFX_DLIGHTS",
235 //"EXT_CSQC" // not ready yet
242 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.
244 setorigin (entity, origin)
247 static void VM_SV_setorigin(prvm_prog_t *prog)
251 VM_SAFEPARMCOUNT(2, VM_SV_setorigin);
253 e = PRVM_G_EDICT(OFS_PARM0);
254 if (e == prog->edicts)
256 VM_Warning(prog, "setorigin: can not modify world entity\n");
261 VM_Warning(prog, "setorigin: can not modify free entity\n");
264 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), PRVM_serveredictvector(e, origin));
265 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
266 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
270 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
271 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qbool rotate)
275 for (i=0 ; i<3 ; i++)
277 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
279 // set derived values
280 VectorCopy (min, PRVM_serveredictvector(e, mins));
281 VectorCopy (max, PRVM_serveredictvector(e, maxs));
282 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
291 the size box is rotated by the current angle
292 LadyHavoc: no it isn't...
294 setsize (entity, minvector, maxvector)
297 static void VM_SV_setsize(prvm_prog_t *prog)
302 VM_SAFEPARMCOUNT(3, VM_SV_setsize);
304 e = PRVM_G_EDICT(OFS_PARM0);
305 if (e == prog->edicts)
307 VM_Warning(prog, "setsize: can not modify world entity\n");
312 VM_Warning(prog, "setsize: can not modify free entity\n");
315 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), mins);
316 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), maxs);
317 SetMinMaxSize(prog, e, mins, maxs, false);
325 setmodel(entity, model)
328 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
329 static void VM_SV_setmodel(prvm_prog_t *prog)
335 VM_SAFEPARMCOUNT(2, VM_SV_setmodel);
337 e = PRVM_G_EDICT(OFS_PARM0);
338 if (e == prog->edicts)
340 VM_Warning(prog, "setmodel: can not modify world entity\n");
345 VM_Warning(prog, "setmodel: can not modify free entity\n");
348 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
349 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
350 PRVM_serveredictfloat(e, modelindex) = i;
352 mod = SV_GetModelByIndex(i);
356 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
357 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
359 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
362 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
369 single print to a specific client
371 sprint(clientent, value)
374 static void VM_SV_sprint(prvm_prog_t *prog)
378 char string[VM_TEMPSTRING_MAXSIZE];
380 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
382 VM_VarString(prog, 1, string, sizeof(string));
384 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
385 // LadyHavoc: div0 requested that sprintto world operate like print
392 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
394 VM_Warning(prog, "tried to centerprint to a non-client\n");
398 client = svs.clients + entnum-1;
399 if (!client->netconnection)
402 MSG_WriteChar(&client->netconnection->message,svc_print);
403 MSG_WriteString(&client->netconnection->message, string);
411 single print to a specific client
413 centerprint(clientent, value)
416 static void VM_SV_centerprint(prvm_prog_t *prog)
420 char string[VM_TEMPSTRING_MAXSIZE];
422 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
424 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
426 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
428 VM_Warning(prog, "tried to centerprint to a non-client\n");
432 client = svs.clients + entnum-1;
433 if (!client->netconnection)
436 VM_VarString(prog, 1, string, sizeof(string));
437 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
438 MSG_WriteString(&client->netconnection->message, string);
445 particle(origin, color, count)
448 static void VM_SV_particle(prvm_prog_t *prog)
454 VM_SAFEPARMCOUNT(4, VM_SV_particle);
456 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
457 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
458 color = (int)PRVM_G_FLOAT(OFS_PARM2);
459 count = (int)PRVM_G_FLOAT(OFS_PARM3);
460 SV_StartParticle (org, dir, color, count);
470 static void VM_SV_ambientsound(prvm_prog_t *prog)
474 prvm_vec_t vol, attenuation;
477 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
479 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
480 samp = PRVM_G_STRING(OFS_PARM1);
481 vol = PRVM_G_FLOAT(OFS_PARM2);
482 attenuation = PRVM_G_FLOAT(OFS_PARM3);
484 // check to see if samp was properly precached
485 soundnum = SV_SoundIndex(samp, 1);
493 if(sv.protocol == PROTOCOL_NEHAHRABJP)
496 // add an svc_spawnambient command to the level signon packet
499 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
501 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
503 MSG_WriteVector(&sv.signon, pos, sv.protocol);
505 if (large || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
506 MSG_WriteShort (&sv.signon, soundnum);
508 MSG_WriteByte (&sv.signon, soundnum);
510 MSG_WriteByte (&sv.signon, (int)(vol*255));
511 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
519 Each entity can have eight independant sound sources, like voice,
522 Channel 0 is an auto-allocate channel, the others override anything
523 already running on that entity/channel pair.
525 An attenuation of 0 will play full volume everywhere in the level.
526 Larger attenuations will drop off.
528 void(entity e, float chan, string samp, float volume[, float atten[, float pitchchange[, float flags]]]) sound (QUAKE)
531 static void VM_SV_sound(prvm_prog_t *prog)
535 prvm_edict_t *entity;
541 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
543 entity = PRVM_G_EDICT(OFS_PARM0);
544 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
545 sample = PRVM_G_STRING(OFS_PARM2);
546 nvolume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
549 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
553 attenuation = PRVM_G_FLOAT(OFS_PARM4);
557 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
562 if(channel >= 8 && channel <= 15) // weird QW feature
564 flags |= CHANNELFLAG_RELIABLE;
570 // LadyHavoc: we only let the qc set certain flags, others are off-limits
571 flags = (int)PRVM_G_FLOAT(OFS_PARM6) & (CHANNELFLAG_RELIABLE | CHANNELFLAG_FORCELOOP | CHANNELFLAG_PAUSED | CHANNELFLAG_FULLVOLUME);
574 if (nvolume < 0 || nvolume > 255)
576 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
580 if (attenuation < 0 || attenuation > 4)
582 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
586 channel = CHAN_USER2ENGINE(channel);
588 if (!IS_CHAN(channel))
590 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
594 SV_StartSound (entity, channel, sample, nvolume, attenuation, flags & CHANNELFLAG_RELIABLE, pitchchange);
601 Follows the same logic as VM_SV_sound, except instead of
602 an entity, an origin for the sound is provided, and channel
603 is omitted (since no entity is being tracked).
607 static void VM_SV_pointsound(prvm_prog_t *prog)
615 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
617 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
618 sample = PRVM_G_STRING(OFS_PARM1);
619 nvolume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
620 attenuation = PRVM_G_FLOAT(OFS_PARM3);
621 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
623 if (nvolume < 0 || nvolume > 255)
625 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
629 if (attenuation < 0 || attenuation > 4)
631 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
635 SV_StartPointSound (org, sample, nvolume, attenuation, pitchchange);
642 Used for use tracing and shot targeting
643 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
644 if the tryents flag is set.
646 traceline (vector1, vector2, movetype, ignore)
649 static void VM_SV_traceline(prvm_prog_t *prog)
656 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
658 prog->xfunction->builtinsprofile += 30;
660 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
661 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), v2);
662 move = (int)PRVM_G_FLOAT(OFS_PARM2);
663 ent = PRVM_G_EDICT(OFS_PARM3);
665 if (isnan(v1[0]) || isnan(v1[1]) || isnan(v1[2]) || isnan(v2[0]) || isnan(v2[1]) || isnan(v2[2]))
666 prog->error_cmd("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
668 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtracelinelength.value);
670 VM_SetTraceGlobals(prog, &trace);
678 Used for use tracing and shot targeting
679 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
680 if the tryents flag is set.
682 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
685 // LadyHavoc: added this for my own use, VERY useful, similar to traceline
686 static void VM_SV_tracebox(prvm_prog_t *prog)
688 vec3_t v1, v2, m1, m2;
693 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
695 prog->xfunction->builtinsprofile += 30;
697 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
698 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), m1);
699 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), m2);
700 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), v2);
701 move = (int)PRVM_G_FLOAT(OFS_PARM4);
702 ent = PRVM_G_EDICT(OFS_PARM5);
704 if (isnan(v1[0]) || isnan(v1[1]) || isnan(v1[2]) || isnan(v2[0]) || isnan(v2[1]) || isnan(v2[2]))
705 prog->error_cmd("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", prog->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));
707 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtraceboxlength.value);
709 VM_SetTraceGlobals(prog, &trace);
712 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
716 vec3_t move, end, tossentorigin, tossentmins, tossentmaxs;
717 vec3_t original_origin;
718 vec3_t original_velocity;
719 vec3_t original_angles;
720 vec3_t original_avelocity;
723 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
724 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
725 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
726 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
728 gravity = PRVM_serveredictfloat(tossent, gravity);
731 gravity *= sv_gravity.value * 0.025;
733 for (i = 0;i < 200;i++) // LadyHavoc: sanity check; never trace more than 10 seconds
735 SV_CheckVelocity (tossent);
736 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
737 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
738 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
739 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
740 VectorCopy(PRVM_serveredictvector(tossent, origin), tossentorigin);
741 VectorCopy(PRVM_serveredictvector(tossent, mins), tossentmins);
742 VectorCopy(PRVM_serveredictvector(tossent, maxs), tossentmaxs);
743 trace = SV_TraceBox(tossentorigin, tossentmins, tossentmaxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent), 0, 0, collision_extendmovelength.value);
744 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
745 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
747 if (trace.fraction < 1)
751 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
752 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
753 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
754 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
759 static void VM_SV_tracetoss(prvm_prog_t *prog)
763 prvm_edict_t *ignore;
765 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
767 prog->xfunction->builtinsprofile += 600;
769 ent = PRVM_G_EDICT(OFS_PARM0);
770 if (ent == prog->edicts)
772 VM_Warning(prog, "tracetoss: can not use world entity\n");
775 ignore = PRVM_G_EDICT(OFS_PARM1);
777 trace = SV_Trace_Toss(prog, ent, ignore);
779 VM_SetTraceGlobals(prog, &trace);
782 //============================================================================
784 static int checkpvsbytes;
785 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
787 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
793 // cycle to the next one
795 check = bound(1, check, svs.maxclients);
796 if (check == svs.maxclients)
804 prog->xfunction->builtinsprofile++;
806 if (i == svs.maxclients+1)
808 // look up the client's edict
809 ent = PRVM_EDICT_NUM(i);
810 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
811 if (i != check && (ent->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
813 // found a valid client (possibly the same one again)
817 // get the PVS for the entity
818 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
820 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
821 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
830 Returns a client (or object that has a client enemy) that would be a
833 If there is more than one valid option, they are cycled each frame
835 If (self.origin + self.viewofs) is not in the PVS of the current target,
836 it is not returned at all.
841 int c_invis, c_notvis;
842 static void VM_SV_checkclient(prvm_prog_t *prog)
844 prvm_edict_t *ent, *self;
847 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
849 // find a new check if on a new frame
850 if (sv.time - sv.lastchecktime >= 0.1)
852 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
853 sv.lastchecktime = sv.time;
856 // return check if it might be visible
857 ent = PRVM_EDICT_NUM(sv.lastcheck);
858 if (ent->free || PRVM_serveredictfloat(ent, health) <= 0)
860 VM_RETURN_EDICT(prog->edicts);
864 // if current entity can't possibly see the check entity, return 0
865 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
866 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
867 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
870 VM_RETURN_EDICT(prog->edicts);
874 // might be able to see it
876 VM_RETURN_EDICT(ent);
879 //============================================================================
885 Checks if an entity is in a point's PVS.
886 Should be fast but can be inexact.
888 float checkpvs(vector viewpos, entity viewee) = #240;
891 static void VM_SV_checkpvs(prvm_prog_t *prog)
893 vec3_t viewpos, absmin, absmax;
894 prvm_edict_t *viewee;
899 unsigned char fatpvs[MAX_MAP_LEAFS/8];
902 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
903 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
904 viewee = PRVM_G_EDICT(OFS_PARM1);
908 VM_Warning(prog, "checkpvs: can not check free entity\n");
909 PRVM_G_FLOAT(OFS_RETURN) = 4;
914 if(!sv.worldmodel || !sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
916 // no PVS support on this worldmodel... darn
917 PRVM_G_FLOAT(OFS_RETURN) = 3;
920 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
923 // viewpos isn't in any PVS... darn
924 PRVM_G_FLOAT(OFS_RETURN) = 2;
927 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
928 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
929 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, absmin, absmax);
931 // using fat PVS like FTEQW does (slow)
932 if(!sv.worldmodel || !sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
934 // no PVS support on this worldmodel... darn
935 PRVM_G_FLOAT(OFS_RETURN) = 3;
938 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
941 // viewpos isn't in any PVS... darn
942 PRVM_G_FLOAT(OFS_RETURN) = 2;
945 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
946 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
947 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, absmin, absmax);
956 Sends text over to the client's execution buffer
958 stuffcmd (clientent, value, ...)
961 static void VM_SV_stuffcmd(prvm_prog_t *prog)
965 char string[VM_TEMPSTRING_MAXSIZE];
967 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
969 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
970 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
972 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
976 VM_VarString(prog, 1, string, sizeof(string));
979 host_client = svs.clients + entnum-1;
980 SV_ClientCommands ("%s", string);
988 Returns a chain of entities that have origins within a spherical area
990 findradius (origin, radius)
993 static void VM_SV_findradius(prvm_prog_t *prog)
995 prvm_edict_t *ent, *chain;
996 vec_t radius, radius2;
997 vec3_t org, eorg, mins, maxs;
1000 static prvm_edict_t *touchedicts[MAX_EDICTS];
1003 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
1006 chainfield = PRVM_G_INT(OFS_PARM2);
1008 chainfield = prog->fieldoffsets.chain;
1010 prog->error_cmd("VM_SV_findradius: %s doesnt have the specified chain field !", prog->name);
1012 chain = (prvm_edict_t *)prog->edicts;
1014 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1015 radius = PRVM_G_FLOAT(OFS_PARM1);
1016 radius2 = radius * radius;
1018 mins[0] = org[0] - (radius + 1);
1019 mins[1] = org[1] - (radius + 1);
1020 mins[2] = org[2] - (radius + 1);
1021 maxs[0] = org[0] + (radius + 1);
1022 maxs[1] = org[1] + (radius + 1);
1023 maxs[2] = org[2] + (radius + 1);
1024 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1025 if (numtouchedicts > MAX_EDICTS)
1027 // this never happens
1028 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1029 numtouchedicts = MAX_EDICTS;
1031 for (i = 0;i < numtouchedicts;i++)
1033 ent = touchedicts[i];
1034 prog->xfunction->builtinsprofile++;
1035 // Quake did not return non-solid entities but darkplaces does
1036 // (note: this is the reason you can't blow up fallen zombies)
1037 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1039 // LadyHavoc: compare against bounding box rather than center so it
1040 // doesn't miss large objects, and use DotProduct instead of Length
1041 // for a major speedup
1042 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1043 if (sv_gameplayfix_findradiusdistancetobox.integer)
1045 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1046 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1047 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1050 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1051 if (DotProduct(eorg, eorg) < radius2)
1053 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1058 VM_RETURN_EDICT(chain);
1065 Returns a chain of entities that are touching a box (a simpler findradius); supports DP_QC_FINDCHAIN_TOFIELD
1067 findbox (mins, maxs)
1070 static void VM_SV_findbox(prvm_prog_t *prog)
1072 prvm_edict_t *chain;
1073 int i, numtouchedicts;
1074 static prvm_edict_t *touchedicts[MAX_EDICTS];
1077 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findbox);
1080 chainfield = PRVM_G_INT(OFS_PARM2);
1082 chainfield = prog->fieldoffsets.chain;
1084 prog->error_cmd("VM_SV_findbox: %s doesnt have the specified chain field !", prog->name);
1086 chain = (prvm_edict_t *)prog->edicts;
1088 numtouchedicts = SV_EntitiesInBox(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), MAX_EDICTS, touchedicts);
1089 if (numtouchedicts > MAX_EDICTS)
1091 // this never happens
1092 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1093 numtouchedicts = MAX_EDICTS;
1095 for (i = 0; i < numtouchedicts; ++i)
1097 prog->xfunction->builtinsprofile++;
1098 PRVM_EDICTFIELDEDICT(touchedicts[i], chainfield) = PRVM_EDICT_TO_PROG(chain);
1099 chain = touchedicts[i];
1102 VM_RETURN_EDICT(chain);
1105 static void VM_SV_precache_sound(prvm_prog_t *prog)
1107 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1108 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1111 static void VM_SV_precache_model(prvm_prog_t *prog)
1113 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1114 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1115 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1122 float(float yaw, float dist[, settrace]) walkmove
1125 static void VM_SV_walkmove(prvm_prog_t *prog)
1134 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1136 // assume failure if it returns early
1137 PRVM_G_FLOAT(OFS_RETURN) = 0;
1139 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1140 if (ent == prog->edicts)
1142 VM_Warning(prog, "walkmove: can not modify world entity\n");
1147 VM_Warning(prog, "walkmove: can not modify free entity\n");
1150 yaw = PRVM_G_FLOAT(OFS_PARM0);
1151 dist = PRVM_G_FLOAT(OFS_PARM1);
1152 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1154 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1157 yaw = yaw*M_PI*2 / 360;
1159 move[0] = cos(yaw)*dist;
1160 move[1] = sin(yaw)*dist;
1163 // save program state, because SV_movestep may call other progs
1164 oldf = prog->xfunction;
1165 oldself = PRVM_serverglobaledict(self);
1167 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1170 // restore program state
1171 prog->xfunction = oldf;
1172 PRVM_serverglobaledict(self) = oldself;
1182 inline static qbool droptofloor_bsp_failcond(trace_t *trace)
1184 if (sv.worldmodel->brush.isq3bsp || sv.worldmodel->brush.isq2bsp)
1185 return trace->startsolid;
1187 return trace->allsolid || trace->fraction == 1;
1189 static void VM_SV_droptofloor(prvm_prog_t *prog)
1195 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1197 // assume failure if it returns early
1198 PRVM_G_FLOAT(OFS_RETURN) = 0;
1200 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1201 if (ent == prog->edicts)
1203 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1208 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1212 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1214 int n = PHYS_NudgeOutOfSolid(prog, ent);
1216 VM_Warning(prog, "droptofloor at \"%f %f %f\": sv_gameplayfix_droptofloorstartsolid_nudgetocorrect COULD NOT FIX badly placed entity \"%s\" before drop\n", PRVM_gameedictvector(ent, origin)[0], PRVM_gameedictvector(ent, origin)[1], PRVM_gameedictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname)));
1218 VM_Warning(prog, "droptofloor at \"%f %f %f\": sv_gameplayfix_droptofloorstartsolid_nudgetocorrect FIXED badly placed entity \"%s\" before drop\n", PRVM_gameedictvector(ent, origin)[0], PRVM_gameedictvector(ent, origin)[1], PRVM_gameedictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname)));
1221 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1222 if (sv.worldmodel->brush.isq3bsp)
1224 else if (sv.worldmodel->brush.isq2bsp)
1227 end[2] -= 256; // Quake, QuakeWorld
1229 /* bones_was_here: not using SV_GenericHitSuperContentsMask(ent) anymore because it was setting:
1230 * items: SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY
1231 * monsters: SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP
1232 * explobox: SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE
1233 * which caused (startsolid == true) when, for example, a health was touching a monster.
1234 * Changing MOVE_NORMAL also fixes that, but other engines are using MOVE_NORMAL here.
1236 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID, 0, 0, collision_extendmovelength.value);
1237 if (droptofloor_bsp_failcond(&trace))
1239 if (sv_gameplayfix_droptofloorstartsolid.integer)
1243 offset[0] = 0.5f * (PRVM_serveredictvector(ent, mins)[0] + PRVM_serveredictvector(ent, maxs)[0]);
1244 offset[1] = 0.5f * (PRVM_serveredictvector(ent, mins)[1] + PRVM_serveredictvector(ent, maxs)[1]);
1245 offset[2] = PRVM_serveredictvector(ent, mins)[2];
1246 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1247 VectorAdd(end, offset, end);
1249 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID, 0, 0, collision_extendmovelength.value);
1250 if (droptofloor_bsp_failcond(&trace))
1252 VM_Warning(prog, "droptofloor at \"%f %f %f\": sv_gameplayfix_droptofloorstartsolid COULD NOT FIX badly placed entity \"%s\"\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname)));
1255 VM_Warning(prog, "droptofloor at \"%f %f %f\": sv_gameplayfix_droptofloorstartsolid FIXED badly placed entity \"%s\"\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname)));
1256 VectorSubtract(trace.endpos, offset, PRVM_serveredictvector(ent, origin));
1258 // only because we dropped it without considering its bbox
1259 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1260 PHYS_NudgeOutOfSolid(prog, ent);
1264 VM_Warning(prog, "droptofloor at \"%f %f %f\": badly placed entity \"%s\", startsolid: %d allsolid: %d\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname)), trace.startsolid, trace.allsolid);
1269 VectorCopy(trace.endpos, PRVM_serveredictvector(ent, origin));
1272 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1273 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1274 PRVM_G_FLOAT(OFS_RETURN) = 1;
1275 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1276 ent->priv.server->suspendedinairflag = true;
1283 void(float style, string value) lightstyle
1286 static void VM_SV_lightstyle(prvm_prog_t *prog)
1293 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1295 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1296 val = PRVM_G_STRING(OFS_PARM1);
1298 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1299 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1302 // change the string in sv
1303 dp_strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1305 // send message to all clients on this server
1306 if (sv.state != ss_active)
1309 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1311 if (client->active && client->netconnection)
1313 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1314 MSG_WriteChar (&client->netconnection->message,style);
1315 MSG_WriteString (&client->netconnection->message, val);
1325 static void VM_SV_checkbottom(prvm_prog_t *prog)
1327 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1328 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1336 static void VM_SV_pointcontents(prvm_prog_t *prog)
1339 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1340 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point);
1341 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(SV_PointSuperContents(point));
1348 Pick a vector for the player to shoot along
1349 vector aim(entity, missilespeed)
1352 static void VM_SV_aim(prvm_prog_t *prog)
1354 prvm_edict_t *ent, *check, *bestent;
1355 vec3_t start, dir, end, bestdir;
1358 float dist, bestdist;
1361 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1363 // assume failure if it returns early
1364 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1365 // if sv_aim is so high it can't possibly accept anything, skip out early
1366 if (sv_aim.value >= 1)
1369 ent = PRVM_G_EDICT(OFS_PARM0);
1370 if (ent == prog->edicts)
1372 VM_Warning(prog, "aim: can not use world entity\n");
1377 VM_Warning(prog, "aim: can not use free entity\n");
1380 //speed = PRVM_G_FLOAT(OFS_PARM1);
1382 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1385 // try sending a trace straight
1386 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1387 VectorMA (start, 2048, dir, end);
1388 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1389 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1390 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1392 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1397 // try all possible entities
1398 VectorCopy (dir, bestdir);
1399 bestdist = sv_aim.value;
1402 check = PRVM_NEXT_EDICT(prog->edicts);
1403 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1405 prog->xfunction->builtinsprofile++;
1406 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1410 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1411 continue; // don't aim at teammate
1412 for (j=0 ; j<3 ; j++)
1413 end[j] = PRVM_serveredictvector(check, origin)[j]
1414 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1415 VectorSubtract (end, start, dir);
1416 VectorNormalize (dir);
1417 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1418 if (dist < bestdist)
1419 continue; // to far to turn
1420 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1421 if (tr.ent == check)
1422 { // can shoot at this one
1430 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1431 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1432 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1434 VectorNormalize (end);
1435 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1439 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1444 ===============================================================================
1448 ===============================================================================
1451 #define MSG_BROADCAST 0 // unreliable to all
1452 #define MSG_ONE 1 // reliable to one (msg_entity)
1453 #define MSG_ALL 2 // reliable to all
1454 #define MSG_INIT 3 // write to the init string
1455 #define MSG_ENTITY 5
1457 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1463 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1467 return &sv.datagram;
1470 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1471 entnum = PRVM_NUM_FOR_EDICT(ent);
1472 if (entnum < 1 || entnum > svs.maxclients)
1474 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1475 return &sv.reliable_datagram;
1477 else if (!svs.clients[entnum-1].active)
1479 VM_Warning(prog, "WriteDest: tried to write to a disconnected client\n");
1480 return &sv.reliable_datagram;
1482 else if (!svs.clients[entnum-1].netconnection)
1484 VM_Warning(prog, "WriteDest: tried to write to a bot client\n");
1485 return &sv.reliable_datagram;
1488 return &svs.clients[entnum-1].netconnection->message;
1491 VM_Warning(prog, "WriteDest: bad destination\n");
1493 return &sv.reliable_datagram;
1499 return sv.writeentitiestoclient_msg;
1505 static void VM_SV_WriteByte(prvm_prog_t *prog)
1507 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1508 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1511 static void VM_SV_WriteChar(prvm_prog_t *prog)
1513 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1514 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1517 static void VM_SV_WriteShort(prvm_prog_t *prog)
1519 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1520 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1523 static void VM_SV_WriteLong(prvm_prog_t *prog)
1525 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1526 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1529 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1531 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1532 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1535 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1537 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1538 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1541 static void VM_SV_WriteString(prvm_prog_t *prog)
1543 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1544 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1547 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1549 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1550 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1554 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1556 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1557 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1560 // writes a picture as at most size bytes of data
1562 // IMGNAME \0 SIZE(short) IMGDATA
1563 // if failed to read/compress:
1565 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1566 static void VM_SV_WritePicture(prvm_prog_t *prog)
1568 const char *imgname;
1572 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1574 imgname = PRVM_G_STRING(OFS_PARM1);
1575 size = (size_t) PRVM_G_FLOAT(OFS_PARM2);
1579 MSG_WriteString(WriteDest(prog), imgname);
1580 if(Image_Compress(imgname, size, &buf, &size))
1583 MSG_WriteShort(WriteDest(prog), (int)size);
1584 SZ_Write(WriteDest(prog), (unsigned char *) buf, (int)size);
1589 MSG_WriteShort(WriteDest(prog), 0);
1593 //////////////////////////////////////////////////////////
1595 static void VM_SV_makestatic(prvm_prog_t *prog)
1600 // allow 0 parameters due to an id1 qc bug in which this function is used
1601 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1602 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1604 if (prog->argc >= 1)
1605 ent = PRVM_G_EDICT(OFS_PARM0);
1607 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1608 if (ent == prog->edicts)
1610 VM_Warning(prog, "makestatic: can not modify world entity\n");
1615 VM_Warning(prog, "makestatic: can not modify free entity\n");
1620 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1623 if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1625 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1626 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1627 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1631 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1632 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1633 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1637 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1638 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1639 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1642 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1643 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1644 for (i=0 ; i<3 ; i++)
1646 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1647 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1650 // throw the entity away now
1651 PRVM_ED_Free(prog, ent);
1654 //=============================================================================
1661 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1667 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1669 ent = PRVM_G_EDICT(OFS_PARM0);
1670 i = PRVM_NUM_FOR_EDICT(ent);
1671 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1673 Con_Print("tried to setspawnparms on a non-client\n");
1677 // copy spawn parms out of the client_t
1678 client = svs.clients + i-1;
1679 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1680 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1687 Returns a color vector indicating the lighting at the requested point.
1689 (Internal Operation note: actually measures the light beneath the point, just like
1690 the model lighting on the client)
1695 static void VM_SV_getlight(prvm_prog_t *prog)
1697 vec3_t ambientcolor, diffusecolor, diffusenormal;
1699 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1700 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
1701 VectorClear(ambientcolor);
1702 VectorClear(diffusecolor);
1703 VectorClear(diffusenormal);
1704 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1705 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1706 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1711 unsigned char type; // 1/2/8 or 0 to indicate unused
1715 static customstat_t vm_customstats[MAX_CL_STATS]; // matches the regular stat numbers, but only MIN_VM_STAT to MAX_VM_STAT range is used if things are working properly (can register stats from MAX_VM_STAT to MAX_CL_STATS but will warn)
1716 static int vm_customstats_last;
1718 void VM_CustomStats_Clear (void)
1720 memset(vm_customstats, 0, sizeof(vm_customstats));
1721 vm_customstats_last = -1;
1724 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1726 prvm_prog_t *prog = SVVM_prog;
1734 for(i=MIN_VM_STAT; i<=vm_customstats_last ;i++)
1736 if(!vm_customstats[i].type)
1738 switch(vm_customstats[i].type)
1740 //string as 16 bytes
1743 dp_strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1744 stats[i] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1745 stats[i+1] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1746 stats[i+2] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1747 stats[i+3] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1749 //float field sent as-is
1751 // can't directly use PRVM_E_INT on the field because it may be PRVM_64 and a double is not the representation we want to send
1752 u.f = PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1755 //integer value of float field
1757 stats[i] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1765 extern cvar_t sv_qcstats;
1767 // void(float index, float type, .void field) SV_AddStat = #232;
1768 // Set up an auto-sent player stat.
1769 // Client's get thier own fields sent to them. Index may not be less than 32.
1770 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1771 // 1: string (4 stats carrying a total of 16 charactures)
1772 // 2: float (one stat, float converted to an integer for transportation)
1773 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1774 static void VM_SV_AddStat(prvm_prog_t *prog)
1778 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1780 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1781 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1782 off = PRVM_G_INT (OFS_PARM2);
1791 VM_Warning(prog, "PF_SV_AddStat: unrecognized type %i - supported types are 1 (string up to 16 bytes, takes 4 stat slots), 2 (truncate to int32), 8 (send as float)", type);
1797 VM_Warning(prog, "PF_SV_AddStat: index (%i) may not be less than %i\n", i, MIN_VM_STAT);
1801 if (i >= MAX_CL_STATS)
1803 VM_Warning(prog, "PF_SV_AddStat: index (%i) >= MAX_CL_STATS (%i), not supported by protocol, and AddStat beyond MAX_VM_STAT (%i) conflicts with engine MOVEVARS\n", i, MAX_CL_STATS, MAX_VM_STAT);
1807 if (i > (MAX_CL_STATS - 4) && type == 1)
1809 VM_Warning(prog, "PF_SV_AddStat: index (%i) > (MAX_CL_STATS (%i) - 4) with string type won't fit in the protocol, and AddStat beyond MAX_VM_STAT conflicts with engine MOVEVARS\n", i, MAX_CL_STATS);
1813 // these are hazardous to override but sort of allowed if one wants to be adventurous... and enjoys warnings.
1814 if (i < MIN_VM_STAT)
1815 VM_Warning(prog, "PF_SV_AddStat: index (%i) < MIN_VM_STAT (%i) may conflict with engine stats - allowed, but this may break things\n", i, MIN_VM_STAT);
1816 else if (i >= MAX_VM_STAT && !sv_qcstats.integer)
1817 VM_Warning(prog, "PF_SV_AddStat: index (%i) >= MAX_VM_STAT (%i) conflicts with engine stats - allowed, but this may break slowmo and stuff\n", i, MAX_VM_STAT);
1818 else if (i > (MAX_VM_STAT - 4) && type == 1 && !sv_qcstats.integer)
1819 VM_Warning(prog, "PF_SV_AddStat: index (%i) >= MAX_VM_STAT (%i) - 4 with string type won't fit within MAX_VM_STAT, thus conflicting with engine stats - allowed, but this may break slowmo and stuff\n", i, MAX_VM_STAT);
1821 vm_customstats[i].type = type;
1822 vm_customstats[i].fieldoffset = off;
1823 if(vm_customstats_last < i)
1824 vm_customstats_last = i;
1831 copies data from one entity to another
1833 copyentity(src, dst)
1836 static void VM_SV_copyentity(prvm_prog_t *prog)
1838 prvm_edict_t *in, *out;
1839 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1840 in = PRVM_G_EDICT(OFS_PARM0);
1841 if (in == prog->edicts)
1843 VM_Warning(prog, "copyentity: can not read world entity\n");
1848 VM_Warning(prog, "copyentity: can not read free entity\n");
1851 out = PRVM_G_EDICT(OFS_PARM1);
1852 if (out == prog->edicts)
1854 VM_Warning(prog, "copyentity: can not modify world entity\n");
1859 VM_Warning(prog, "copyentity: can not modify free entity\n");
1862 memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
1872 sets the color of a client and broadcasts the update to all connected clients
1874 setcolor(clientent, value)
1877 static void VM_SV_setcolor(prvm_prog_t *prog)
1882 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1883 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1884 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1886 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1888 Con_Print("tried to setcolor a non-client\n");
1892 client = svs.clients + entnum-1;
1895 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1896 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1899 if (client->old_colors != client->colors)
1901 client->old_colors = client->colors;
1902 // send notification to all clients
1903 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1904 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1905 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1913 effect(origin, modelname, startframe, framecount, framerate)
1916 static void VM_SV_effect(prvm_prog_t *prog)
1921 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1922 s = PRVM_G_STRING(OFS_PARM1);
1925 VM_Warning(prog, "effect: no model specified\n");
1929 i = SV_ModelIndex(s, 1);
1932 VM_Warning(prog, "effect: model not precached\n");
1936 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1938 VM_Warning(prog, "effect: framecount < 1\n");
1942 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1944 VM_Warning(prog, "effect: framerate < 1\n");
1948 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1949 SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1952 static void VM_SV_te_blood(prvm_prog_t *prog)
1954 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1955 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1957 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1958 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1964 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1965 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1966 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1968 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1969 SV_FlushBroadcastMessages();
1972 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1974 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1975 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1977 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1978 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1980 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1984 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1985 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1990 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1991 SV_FlushBroadcastMessages();
1994 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1996 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1997 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1998 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2000 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2001 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2002 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2004 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
2005 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
2006 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
2007 SV_FlushBroadcastMessages();
2010 static void VM_SV_te_particlecube(prvm_prog_t *prog)
2012 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
2013 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2015 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2016 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2018 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2019 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2020 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2022 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2023 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2024 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2026 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2028 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2030 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2032 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2033 // gravity true/false
2034 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
2036 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
2037 SV_FlushBroadcastMessages();
2040 static void VM_SV_te_particlerain(prvm_prog_t *prog)
2042 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
2043 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2045 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2046 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2048 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2049 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2050 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2052 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2054 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2056 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2058 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2060 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2062 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2063 SV_FlushBroadcastMessages();
2066 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
2068 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
2069 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2071 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2072 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2074 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2075 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2076 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2078 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2079 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2080 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2082 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2083 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2084 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2086 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2088 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2089 SV_FlushBroadcastMessages();
2092 static void VM_SV_te_spark(prvm_prog_t *prog)
2094 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
2095 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2097 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2098 MSG_WriteByte(&sv.datagram, TE_SPARK);
2100 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2101 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2102 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2104 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2105 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2106 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2108 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2109 SV_FlushBroadcastMessages();
2112 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2114 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2115 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2116 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2118 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2119 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2120 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2121 SV_FlushBroadcastMessages();
2124 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2126 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2127 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2128 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2130 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2131 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2132 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2133 SV_FlushBroadcastMessages();
2136 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2138 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2139 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2140 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2142 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2143 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2144 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2145 SV_FlushBroadcastMessages();
2148 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2150 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2151 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2152 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2154 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2155 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2156 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2157 SV_FlushBroadcastMessages();
2160 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2162 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2163 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2164 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2166 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2167 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2168 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2169 SV_FlushBroadcastMessages();
2172 static void VM_SV_te_customflash(prvm_prog_t *prog)
2174 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2175 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2177 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2178 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2180 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2181 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2182 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2184 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2186 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2188 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2189 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2190 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2191 SV_FlushBroadcastMessages();
2194 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2196 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2197 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2198 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2200 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2201 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2202 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2203 SV_FlushBroadcastMessages();
2206 static void VM_SV_te_spike(prvm_prog_t *prog)
2208 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2209 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2210 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2212 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2213 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2214 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2215 SV_FlushBroadcastMessages();
2218 static void VM_SV_te_superspike(prvm_prog_t *prog)
2220 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2221 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2222 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2224 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2225 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2226 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2227 SV_FlushBroadcastMessages();
2230 static void VM_SV_te_explosion(prvm_prog_t *prog)
2232 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2233 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2234 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2236 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2237 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2238 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2239 SV_FlushBroadcastMessages();
2242 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2244 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2245 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2246 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2248 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2249 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2250 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2251 SV_FlushBroadcastMessages();
2254 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2256 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2257 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2258 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2260 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2261 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2262 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2263 SV_FlushBroadcastMessages();
2266 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2268 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2269 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2270 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2272 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2273 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2274 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2275 SV_FlushBroadcastMessages();
2278 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2280 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2281 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2282 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2284 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2285 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2286 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2287 SV_FlushBroadcastMessages();
2290 static void VM_SV_te_teleport(prvm_prog_t *prog)
2292 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2293 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2294 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2296 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2297 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2298 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2299 SV_FlushBroadcastMessages();
2302 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2304 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2305 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2306 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2308 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2309 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2310 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2312 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2313 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2314 SV_FlushBroadcastMessages();
2317 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2319 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2320 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2321 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2323 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2325 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2326 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2327 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2329 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2330 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2331 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2332 SV_FlushBroadcastMessages();
2335 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2337 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2338 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2339 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2341 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2343 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2344 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2345 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2347 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2348 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2349 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2350 SV_FlushBroadcastMessages();
2353 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2355 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2356 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2357 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2359 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2361 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2362 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2363 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2365 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2366 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2367 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2368 SV_FlushBroadcastMessages();
2371 static void VM_SV_te_beam(prvm_prog_t *prog)
2373 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2374 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2375 MSG_WriteByte(&sv.datagram, TE_BEAM);
2377 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2379 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2380 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2381 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2383 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2384 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2385 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2386 SV_FlushBroadcastMessages();
2389 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2391 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2392 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2393 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2394 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2395 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2396 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2397 SV_FlushBroadcastMessages();
2400 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2402 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2403 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2404 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2406 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2407 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2408 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2410 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2411 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2412 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2414 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2415 SV_FlushBroadcastMessages();
2418 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2419 //this function originally written by KrimZon, made shorter by LadyHavoc
2420 static void VM_SV_clientcommand(prvm_prog_t *prog)
2422 client_t *temp_client;
2424 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2426 //find client for this entity
2427 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2428 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2430 Con_Print("PF_clientcommand: entity is not a client\n");
2434 temp_client = host_client;
2435 host_client = svs.clients + i;
2436 Cmd_ExecuteString(cmd_serverfromclient, PRVM_G_STRING(OFS_PARM1), strlen(PRVM_G_STRING(OFS_PARM1)), src_client, true);
2437 host_client = temp_client;
2440 //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)
2441 static void VM_SV_setattachment(prvm_prog_t *prog)
2443 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2444 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2445 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2448 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2450 if (e == prog->edicts)
2452 VM_Warning(prog, "setattachment: can not modify world entity\n");
2457 VM_Warning(prog, "setattachment: can not modify free entity\n");
2461 if (tagentity == NULL)
2462 tagentity = prog->edicts;
2466 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2468 model = SV_GetModelFromEdict(tagentity);
2471 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2473 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);
2476 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));
2479 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2480 PRVM_serveredictfloat(e, tag_index) = tagindex;
2483 /////////////////////////////////////////
2484 // DP_MD3_TAGINFO extension coded by VorteX
2486 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2490 i = (int)PRVM_serveredictfloat(e, modelindex);
2491 if (i < 1 || i >= MAX_MODELS)
2494 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2497 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2504 Matrix4x4_CreateIdentity(tag_localmatrix);
2506 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2508 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2519 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qbool viewmatrix)
2522 float pitchsign = 1;
2524 scale = PRVM_serveredictfloat(ent, scale);
2529 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);
2532 pitchsign = SV_GetPitchSign(prog, ent);
2533 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);
2537 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2540 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2542 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2543 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2544 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2545 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2547 *out = identitymatrix;
2551 // Warnings/errors code:
2552 // 0 - normal (everything all-right)
2555 // 3 - null or non-precached model
2556 // 4 - no tags with requested index
2557 // 5 - runaway loop at attachment chain
2558 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2561 int modelindex, attachloop;
2562 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2565 *out = identitymatrix; // warnings and errors return identical matrix
2567 if (ent == prog->edicts)
2572 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2573 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2576 model = SV_GetModelByIndex(modelindex);
2578 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2579 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2580 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2582 tagmatrix = identitymatrix;
2583 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2587 if (attachloop >= 256) // prevent runaway looping
2589 // apply transformation by child's tagindex on parent entity and then
2590 // by parent entity itself
2591 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2592 if (ret && attachloop == 0)
2594 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2595 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2596 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2597 // next iteration we process the parent entity
2598 if (PRVM_serveredictedict(ent, tag_entity))
2600 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2601 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2608 // RENDER_VIEWMODEL magic
2609 if (PRVM_serveredictedict(ent, viewmodelforclient))
2611 Matrix4x4_Copy(&tagmatrix, out);
2612 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2614 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2615 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2620 //float(entity ent, string tagname) gettagindex;
2622 static void VM_SV_gettagindex(prvm_prog_t *prog)
2625 const char *tag_name;
2628 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2630 ent = PRVM_G_EDICT(OFS_PARM0);
2631 tag_name = PRVM_G_STRING(OFS_PARM1);
2633 if (ent == prog->edicts)
2635 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2640 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2645 if (!SV_GetModelFromEdict(ent))
2646 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2649 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2651 if(developer_extra.integer)
2652 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2654 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2657 //vector(entity ent, float tagindex) gettaginfo;
2658 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2662 matrix4x4_t tag_matrix;
2663 matrix4x4_t tag_localmatrix;
2665 const char *tagname;
2667 vec3_t forward, left, up, origin;
2668 const model_t *model;
2670 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2672 e = PRVM_G_EDICT(OFS_PARM0);
2673 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2675 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2676 Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
2677 VectorCopy(forward, PRVM_serverglobalvector(v_forward));
2678 VectorNegate(left, PRVM_serverglobalvector(v_right));
2679 VectorCopy(up, PRVM_serverglobalvector(v_up));
2680 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2681 model = SV_GetModelFromEdict(e);
2682 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2683 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2684 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2685 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2686 Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
2688 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2689 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname, strlen(tagname)) : 0;
2690 VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
2691 VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
2692 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2693 VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset));
2698 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2701 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2704 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2707 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2710 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2715 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2716 static void VM_SV_dropclient(prvm_prog_t *prog)
2719 client_t *oldhostclient;
2720 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2721 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2722 if (clientnum < 0 || clientnum >= svs.maxclients)
2724 VM_Warning(prog, "dropclient: not a client\n");
2727 if (!svs.clients[clientnum].active)
2729 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2732 oldhostclient = host_client;
2733 host_client = svs.clients + clientnum;
2734 SV_DropClient(false, "Client dropped");
2735 host_client = oldhostclient;
2738 //entity() spawnclient (DP_SV_BOTCLIENT)
2739 static void VM_SV_spawnclient(prvm_prog_t *prog)
2743 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2744 prog->xfunction->builtinsprofile += 2;
2746 for (i = 0;i < svs.maxclients;i++)
2748 if (!svs.clients[i].active)
2750 prog->xfunction->builtinsprofile += 100;
2751 SV_ConnectClient (i, NULL);
2752 // this has to be set or else ClientDisconnect won't be called
2753 // we assume the qc will call ClientConnect...
2754 svs.clients[i].clientconnectcalled = true;
2755 ed = PRVM_EDICT_NUM(i + 1);
2759 VM_RETURN_EDICT(ed);
2762 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2763 static void VM_SV_clienttype(prvm_prog_t *prog)
2766 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2767 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2768 if (clientnum < 0 || clientnum >= svs.maxclients)
2769 PRVM_G_FLOAT(OFS_RETURN) = 3; // CLIENTTYPE_NOTACLIENT
2770 else if (!svs.clients[clientnum].active)
2771 PRVM_G_FLOAT(OFS_RETURN) = 0; // CLIENTTYPE_DISCONNECTED
2772 else if (svs.clients[clientnum].netconnection)
2773 PRVM_G_FLOAT(OFS_RETURN) = 1; // CLIENTTYPE_REAL
2775 PRVM_G_FLOAT(OFS_RETURN) = 2; // CLIENTTYPE_BOT
2782 string(string key) serverkey
2785 static void VM_SV_serverkey(prvm_prog_t *prog)
2787 char string[VM_TEMPSTRING_MAXSIZE];
2789 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2790 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2791 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string, strlen(string));
2794 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2795 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2800 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2802 e = PRVM_G_EDICT(OFS_PARM0);
2803 if (e == prog->edicts)
2805 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2810 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2813 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2814 if (i <= 0 || i >= MAX_MODELS)
2816 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2819 if (!sv.model_precache[i][0])
2821 VM_Warning(prog, "setmodelindex: model not precached\n");
2825 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2826 PRVM_serveredictfloat(e, modelindex) = i;
2828 mod = SV_GetModelByIndex(i);
2832 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2833 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2835 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2838 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2841 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2842 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2845 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2847 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2849 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2850 if (i <= 0 || i >= MAX_MODELS)
2852 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2855 if (!sv.model_precache[i][0])
2857 VM_Warning(prog, "modelnameforindex: model not precached\n");
2861 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2864 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2865 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2868 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2869 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2872 PRVM_G_FLOAT(OFS_RETURN) = i;
2875 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2876 static void VM_SV_trailparticles(prvm_prog_t *prog)
2879 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2881 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2884 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2885 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2886 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2887 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start);
2888 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end);
2889 MSG_WriteVector(&sv.datagram, start, sv.protocol);
2890 MSG_WriteVector(&sv.datagram, end, sv.protocol);
2891 SV_FlushBroadcastMessages();
2894 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2895 static void VM_SV_pointparticles(prvm_prog_t *prog)
2897 int effectnum, count;
2899 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2901 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2904 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2905 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2906 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2907 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2908 if (count == 1 && !VectorLength2(vel))
2911 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2912 MSG_WriteShort(&sv.datagram, effectnum);
2913 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2917 // 1+2+12+12+2=29 bytes
2918 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2919 MSG_WriteShort(&sv.datagram, effectnum);
2920 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2921 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2922 MSG_WriteShort(&sv.datagram, count);
2925 SV_FlushBroadcastMessages();
2928 qbool SV_VM_ConsoleCommand(const char *text, size_t textlen)
2930 prvm_prog_t *prog = SVVM_prog;
2931 return PRVM_ConsoleCommand(prog, text, textlen, &prog->funcoffsets.ConsoleCmd, true, PRVM_EDICT_TO_PROG(sv.world.prog->edicts), sv.time, "QC function ConsoleCmd is missing");
2934 // #352 void(string cmdname) registercommand (EXT_CSQC)
2935 static void VM_SV_registercommand (prvm_prog_t *prog)
2937 VM_SAFEPARMCOUNT(1, VM_SV_registercmd);
2938 Cmd_AddCommand(CF_SERVER, PRVM_G_STRING(OFS_PARM0), NULL, "console command created by QuakeC");
2941 //PF_setpause, // void(float pause) setpause = #531;
2942 static void VM_SV_setpause(prvm_prog_t *prog) {
2944 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2945 if (pauseValue != 0) { //pause the game
2947 sv.pausedstart = host.realtime;
2948 } else { //disable pause, in case it was enabled
2949 if (sv.paused != 0) {
2954 // send notification to all clients
2955 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2956 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2959 // #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.
2960 static void VM_SV_skel_create(prvm_prog_t *prog)
2962 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2963 model_t *model = SV_GetModelByIndex(modelindex);
2964 skeleton_t *skeleton;
2966 PRVM_G_FLOAT(OFS_RETURN) = 0;
2967 if (!model || !model->num_bones)
2969 for (i = 0;i < MAX_EDICTS;i++)
2970 if (!prog->skeletons[i])
2972 if (i == MAX_EDICTS)
2974 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(prog->progs_mempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2975 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2976 skeleton->model = model;
2977 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2978 // initialize to identity matrices
2979 for (i = 0;i < skeleton->model->num_bones;i++)
2980 skeleton->relativetransforms[i] = identitymatrix;
2983 // #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
2984 static void VM_SV_skel_build(prvm_prog_t *prog)
2986 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2987 skeleton_t *skeleton;
2988 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2989 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2990 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2991 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2992 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2993 model_t *model = SV_GetModelByIndex(modelindex);
2997 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2998 frameblend_t frameblend[MAX_FRAMEBLENDS];
2999 matrix4x4_t bonematrix;
3001 PRVM_G_FLOAT(OFS_RETURN) = 0;
3002 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3004 firstbone = max(0, firstbone);
3005 lastbone = min(lastbone, model->num_bones - 1);
3006 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3007 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
3008 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time);
3009 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
3011 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3013 memset(&bonematrix, 0, sizeof(bonematrix));
3014 for (blendindex = 0;blendindex < numblends;blendindex++)
3016 Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
3017 Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp);
3019 Matrix4x4_Normalize3(&bonematrix, &bonematrix);
3020 Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac);
3022 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
3025 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3026 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
3028 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3029 skeleton_t *skeleton;
3030 PRVM_G_FLOAT(OFS_RETURN) = 0;
3031 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3033 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
3036 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
3037 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
3039 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3040 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3041 skeleton_t *skeleton;
3042 PRVM_G_INT(OFS_RETURN) = 0;
3043 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3045 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3047 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name, strlen(skeleton->model->data_bones[bonenum].name));
3050 // #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)
3051 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
3053 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3054 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3055 skeleton_t *skeleton;
3056 PRVM_G_FLOAT(OFS_RETURN) = 0;
3057 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3059 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3061 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
3064 // #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
3065 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
3067 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3068 const char *tagname = PRVM_G_STRING(OFS_PARM1);
3069 skeleton_t *skeleton;
3070 PRVM_G_FLOAT(OFS_RETURN) = 0;
3071 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3073 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
3076 // #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)
3077 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
3079 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3080 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3081 skeleton_t *skeleton;
3083 vec3_t forward, left, up, origin;
3084 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3085 VectorClear(PRVM_clientglobalvector(v_forward));
3086 VectorClear(PRVM_clientglobalvector(v_right));
3087 VectorClear(PRVM_clientglobalvector(v_up));
3088 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3090 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3092 matrix = skeleton->relativetransforms[bonenum];
3093 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3094 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3095 VectorNegate(left, PRVM_clientglobalvector(v_right));
3096 VectorCopy(up, PRVM_clientglobalvector(v_up));
3097 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3100 // #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)
3101 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
3103 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3104 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3105 skeleton_t *skeleton;
3108 vec3_t forward, left, up, origin;
3109 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3110 VectorClear(PRVM_clientglobalvector(v_forward));
3111 VectorClear(PRVM_clientglobalvector(v_right));
3112 VectorClear(PRVM_clientglobalvector(v_up));
3113 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3115 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3117 matrix = skeleton->relativetransforms[bonenum];
3118 // convert to absolute
3119 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3122 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3124 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3125 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3126 VectorNegate(left, PRVM_clientglobalvector(v_right));
3127 VectorCopy(up, PRVM_clientglobalvector(v_up));
3128 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3131 // #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)
3132 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3134 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3135 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3136 vec3_t forward, left, up, origin;
3137 skeleton_t *skeleton;
3139 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3141 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3143 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3144 VectorNegate(PRVM_clientglobalvector(v_right), left);
3145 VectorCopy(PRVM_clientglobalvector(v_up), up);
3146 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3147 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3148 skeleton->relativetransforms[bonenum] = matrix;
3151 // #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)
3152 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3154 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3155 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3156 vec3_t forward, left, up, origin;
3157 skeleton_t *skeleton;
3160 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3162 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3164 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3165 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3166 VectorNegate(PRVM_clientglobalvector(v_right), left);
3167 VectorCopy(PRVM_clientglobalvector(v_up), up);
3168 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3169 temp = skeleton->relativetransforms[bonenum];
3170 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3173 // #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)
3174 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3176 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3177 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3178 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3180 vec3_t forward, left, up, origin;
3181 skeleton_t *skeleton;
3184 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3186 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3187 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3188 VectorNegate(PRVM_clientglobalvector(v_right), left);
3189 VectorCopy(PRVM_clientglobalvector(v_up), up);
3190 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3191 firstbone = max(0, firstbone);
3192 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3193 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3195 temp = skeleton->relativetransforms[bonenum];
3196 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3200 // #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
3201 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3203 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3204 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3205 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3206 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3208 skeleton_t *skeletondst;
3209 skeleton_t *skeletonsrc;
3210 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3212 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3214 firstbone = max(0, firstbone);
3215 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3216 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3217 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3218 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3221 // #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)
3222 static void VM_SV_skel_delete(prvm_prog_t *prog)
3224 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3225 skeleton_t *skeleton;
3226 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3229 prog->skeletons[skeletonindex] = NULL;
3232 // #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
3233 static void VM_SV_frameforname(prvm_prog_t *prog)
3235 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3236 model_t *model = SV_GetModelByIndex(modelindex);
3237 const char *name = PRVM_G_STRING(OFS_PARM1);
3239 PRVM_G_FLOAT(OFS_RETURN) = -1;
3240 if (!model || !model->animscenes)
3242 for (i = 0;i < model->numframes;i++)
3244 if (!strcasecmp(model->animscenes[i].name, name))
3246 PRVM_G_FLOAT(OFS_RETURN) = i;
3252 // #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.
3253 static void VM_SV_frameduration(prvm_prog_t *prog)
3255 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3256 model_t *model = SV_GetModelByIndex(modelindex);
3257 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3258 PRVM_G_FLOAT(OFS_RETURN) = 0;
3259 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3261 if (model->animscenes[framenum].framerate)
3262 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3266 prvm_builtin_t vm_sv_builtins[] = {
3267 NULL, // #0 NULL function (not callable) (QUAKE)
3268 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3269 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3270 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3271 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3272 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3273 VM_break, // #6 void() break (QUAKE)
3274 VM_random, // #7 float() random (QUAKE)
3275 VM_SV_sound, // #8 void(entity e, float chan, string samp, float volume[, float atten[, float pitchchange[, float flags]]]) sound (QUAKE)
3276 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3277 VM_error, // #10 void(string e) error (QUAKE)
3278 VM_objerror, // #11 void(string e) objerror (QUAKE)
3279 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3280 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3281 VM_spawn, // #14 entity() spawn (QUAKE)
3282 VM_remove, // #15 void(entity e) remove (QUAKE)
3283 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3284 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3285 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3286 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3287 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3288 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3289 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3290 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3291 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3292 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3293 VM_ftos, // #26 string(float f) ftos (QUAKE)
3294 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3295 VM_coredump, // #28 void() coredump (QUAKE)
3296 VM_traceon, // #29 void() traceon (QUAKE)
3297 VM_traceoff, // #30 void() traceoff (QUAKE)
3298 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3299 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3300 NULL, // #33 (QUAKE)
3301 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3302 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3303 VM_rint, // #36 float(float v) rint (QUAKE)
3304 VM_floor, // #37 float(float v) floor (QUAKE)
3305 VM_ceil, // #38 float(float v) ceil (QUAKE)
3306 NULL, // #39 (QUAKE)
3307 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3308 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3309 NULL, // #42 (QUAKE)
3310 VM_fabs, // #43 float(float f) fabs (QUAKE)
3311 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3312 VM_cvar, // #45 float(string s) cvar (QUAKE)
3313 VM_localcmd_server, // #46 void(string s) localcmd (QUAKE)
3314 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3315 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3316 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3317 NULL, // #50 (QUAKE)
3318 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3319 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3320 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3321 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3322 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3323 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3324 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3325 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3326 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3327 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3328 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3329 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3330 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3331 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3332 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3333 NULL, // #66 (QUAKE)
3334 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3335 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3336 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3337 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3338 NULL, // #71 (QUAKE)
3339 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3340 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3341 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3342 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3343 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3344 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3345 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3346 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3347 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3348 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3349 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3350 NULL, // #83 (QUAKE)
3351 NULL, // #84 (QUAKE)
3352 NULL, // #85 (QUAKE)
3353 NULL, // #86 (QUAKE)
3354 NULL, // #87 (QUAKE)
3355 NULL, // #88 (QUAKE)
3356 NULL, // #89 (QUAKE)
3357 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3358 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3359 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3360 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3361 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3362 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3363 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3364 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3365 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3366 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3367 // FrikaC and Telejano range #100-#199
3378 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3379 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3380 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3381 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3382 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3383 VM_strcat, // #115 string(string s, string...) strcat (FRIK_FILE)
3384 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3385 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3386 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3387 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3468 // FTEQW range #200-#299
3487 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3490 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3491 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3492 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3493 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3494 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3495 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3496 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3497 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3498 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3499 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3501 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3509 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3532 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.
3533 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
3534 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3535 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3536 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)
3537 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
3538 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)
3539 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)
3540 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)
3541 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)
3542 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)
3543 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
3544 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)
3545 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
3546 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.
3569 // CSQC range #300-#399
3570 NULL, // #300 void() clearscene (EXT_CSQC)
3571 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3572 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3573 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3574 NULL, // #304 void() renderscene (EXT_CSQC)
3575 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3576 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3577 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3578 NULL, // #308 void() R_EndPolygon
3580 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3581 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3585 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3586 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3587 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3588 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3589 NULL, // #319 void(string name) freepic (EXT_CSQC)
3590 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3591 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3592 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3593 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3594 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3595 NULL, // #325 void(void) drawresetcliparea
3600 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3601 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3602 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3603 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3604 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3605 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3606 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3607 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3608 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3609 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3610 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3611 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3612 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3613 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3614 NULL, // #344 vector() getmousepos (EXT_CSQC)
3615 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3616 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3617 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3618 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3619 NULL, // #349 float() isdemo (EXT_CSQC)
3620 VM_isserver, // #350 float() isserver (EXT_CSQC)
3621 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3622 VM_SV_registercommand, // #352 void(string cmdname) registercommand (EXT_CSQC)
3623 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3624 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3630 NULL, // #360 float() readbyte (EXT_CSQC)
3631 NULL, // #361 float() readchar (EXT_CSQC)
3632 NULL, // #362 float() readshort (EXT_CSQC)
3633 NULL, // #363 float() readlong (EXT_CSQC)
3634 NULL, // #364 float() readcoord (EXT_CSQC)
3635 NULL, // #365 float() readangle (EXT_CSQC)
3636 NULL, // #366 string() readstring (EXT_CSQC)
3637 NULL, // #367 float() readfloat (EXT_CSQC)
3670 // LadyHavoc's range #400-#499
3671 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3672 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3673 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3674 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3675 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3676 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3677 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3678 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3679 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)
3680 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3681 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3682 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3683 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3684 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3685 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3686 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3687 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3688 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3689 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3690 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3691 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3692 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3693 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3694 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3695 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3696 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3697 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3698 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3699 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3700 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3701 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3702 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3703 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3704 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3705 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3706 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3707 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3708 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3709 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3710 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3711 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3712 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3713 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3714 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3715 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3716 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3717 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3718 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3719 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3720 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3721 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3722 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3723 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3724 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3725 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3726 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3727 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3728 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3730 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3731 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3732 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3733 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3734 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3735 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3736 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3737 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3738 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3739 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3740 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3742 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3743 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3744 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3745 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3746 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3747 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3748 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3749 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3750 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3751 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3752 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3753 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3754 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3755 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3756 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3757 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3765 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3766 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3767 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3768 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3769 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3770 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3771 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3772 VM_SV_WritePicture, // #501
3774 VM_whichpack, // #503 string(string) whichpack = #503;
3781 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3782 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3783 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3784 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)
3785 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3786 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3787 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3788 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3789 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3790 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3800 VM_loadfromdata, // #529
3801 VM_loadfromfile, // #530
3802 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3804 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3805 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3806 VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP)
3807 VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP)
3808 VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP)
3809 VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP)
3811 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3812 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3813 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3837 VM_SV_findbox, // #566 entity(vector mins, vector maxs) findbox = #566; (DP_QC_FINDBOX)
3838 VM_nudgeoutofsolid, // #567 float(entity ent) nudgeoutofsolid = #567; (DP_QC_NUDGEOUTOFSOLID)
3876 VM_callfunction, // #605
3877 VM_writetofile, // #606
3878 VM_isfunction, // #607
3884 VM_parseentitydata, // #613
3895 VM_SV_getextresponse, // #624 string getextresponse(void)
3898 VM_sprintf, // #627 string sprintf(string format, ...)
3899 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3900 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3910 VM_digest_hex, // #639
3913 VM_coverage, // #642
3917 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3919 void SVVM_init_cmd(prvm_prog_t *prog)
3924 void SVVM_reset_cmd(prvm_prog_t *prog)
3926 World_End(&sv.world);