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",
104 "DP_QC_FINDCHAINFLAGS",
105 "DP_QC_FINDCHAINFLOAT",
106 "DP_QC_FINDCHAIN_TOFIELD",
112 "DP_QC_GETSURFACETRIANGLE",
113 "DP_QC_GETSURFACEPOINTATTRIBUTE",
115 "DP_QC_GETTAGINFO_BONEPROPERTIES",
117 "DP_QC_GETTIME_CDTRACK",
121 "DP_QC_MULTIPLETEMPSTRINGS",
122 "DP_QC_NUM_FOR_EDICT",
124 "DP_QC_SINCOSSQRTPOW",
127 "DP_QC_STRINGBUFFERS",
128 "DP_QC_STRINGBUFFERS_CVARLIST",
129 "DP_QC_STRINGBUFFERS_EXT_WIP",
130 "DP_QC_STRINGCOLORFUNCTIONS",
131 "DP_QC_STRING_CASE_FUNCTIONS",
133 "DP_QC_TOKENIZEBYSEPARATOR",
134 "DP_QC_TOKENIZE_CONSOLE",
137 "DP_QC_TRACE_MOVETYPE_HITMODEL",
138 "DP_QC_TRACE_MOVETYPE_WORLDONLY",
139 "DP_QC_UNLIMITEDTEMPSTRINGS",
143 "DP_QC_VECTOANGLES_WITH_ROLL",
144 "DP_QC_VECTORVECTORS",
151 "DP_SKELETONOBJECTS",
152 "DP_SND_DIRECTIONLESSATTNNONE",
154 "DP_SND_SOUND7_WIP1",
155 "DP_SND_SOUND7_WIP2",
159 "DP_SND_GETSOUNDTIME",
161 "DP_VIDEO_SUBTITLES",
165 "DP_SV_BOUNCEFACTOR",
166 "DP_SV_CLIENTCAMERA",
167 "DP_SV_CLIENTCOLORS",
170 "DP_SV_CUSTOMIZEENTITYFORCLIENT",
171 "DP_SV_DISABLECLIENTPREDICTION",
172 "DP_SV_DISCARDABLEDEMO",
173 "DP_SV_DRAWONLYTOCLIENT",
176 "DP_SV_ENTITYCONTENTSTRANSITION",
177 "DP_SV_MODELFLAGS_AS_EFFECTS",
178 "DP_SV_MOVETYPESTEP_LANDEVENT",
180 "DP_SV_NODRAWTOCLIENT",
181 "DP_SV_ONENTITYNOSPAWNFUNCTION",
182 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION",
184 "DP_SV_PING_PACKETLOSS",
185 "DP_SV_PLAYERPHYSICS",
187 "DP_SV_POINTPARTICLES",
189 "DP_SV_PRECACHEANYTIME",
193 "DP_SV_ROTATINGBMODEL",
197 "DP_SV_SPAWNFUNC_PREFIX",
198 "DP_SV_WRITEPICTURE",
199 "DP_SV_WRITEUNTERMINATEDSTRING",
203 "DP_TE_EXPLOSIONRGB",
205 "DP_TE_PARTICLECUBE",
206 "DP_TE_PARTICLERAIN",
207 "DP_TE_PARTICLESNOW",
209 "DP_TE_QUADEFFECTS1",
212 "DP_TE_STANDARDEFFECTBUILTINS",
213 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO"
218 "FTE_CSQC_SKELETONOBJECTS",
221 "KRIMZON_SV_PARSECLIENTCOMMAND",
224 "NEXUIZ_PLAYERMODEL",
226 "PRYDON_CLIENTCURSOR",
227 "TENEBRAE_GFX_DLIGHTS",
231 "DP_QC_FS_SEARCH_PACKFILE",
234 //"EXT_CSQC" // not ready yet
241 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.
243 setorigin (entity, origin)
246 static void VM_SV_setorigin(prvm_prog_t *prog)
250 VM_SAFEPARMCOUNT(2, VM_SV_setorigin);
252 e = PRVM_G_EDICT(OFS_PARM0);
253 if (e == prog->edicts)
255 VM_Warning(prog, "setorigin: can not modify world entity\n");
260 VM_Warning(prog, "setorigin: can not modify free entity\n");
263 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), PRVM_serveredictvector(e, origin));
264 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
265 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
269 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
270 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qbool rotate)
274 for (i=0 ; i<3 ; i++)
276 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
278 // set derived values
279 VectorCopy (min, PRVM_serveredictvector(e, mins));
280 VectorCopy (max, PRVM_serveredictvector(e, maxs));
281 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
290 the size box is rotated by the current angle
291 LadyHavoc: no it isn't...
293 setsize (entity, minvector, maxvector)
296 static void VM_SV_setsize(prvm_prog_t *prog)
301 VM_SAFEPARMCOUNT(3, VM_SV_setsize);
303 e = PRVM_G_EDICT(OFS_PARM0);
304 if (e == prog->edicts)
306 VM_Warning(prog, "setsize: can not modify world entity\n");
311 VM_Warning(prog, "setsize: can not modify free entity\n");
314 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), mins);
315 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), maxs);
316 SetMinMaxSize(prog, e, mins, maxs, false);
324 setmodel(entity, model)
327 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
328 static void VM_SV_setmodel(prvm_prog_t *prog)
334 VM_SAFEPARMCOUNT(2, VM_SV_setmodel);
336 e = PRVM_G_EDICT(OFS_PARM0);
337 if (e == prog->edicts)
339 VM_Warning(prog, "setmodel: can not modify world entity\n");
344 VM_Warning(prog, "setmodel: can not modify free entity\n");
347 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
348 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
349 PRVM_serveredictfloat(e, modelindex) = i;
351 mod = SV_GetModelByIndex(i);
355 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
356 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
358 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
361 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
368 single print to a specific client
370 sprint(clientent, value)
373 static void VM_SV_sprint(prvm_prog_t *prog)
377 char string[VM_STRINGTEMP_LENGTH];
379 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
381 VM_VarString(prog, 1, string, sizeof(string));
383 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
384 // LadyHavoc: div0 requested that sprintto world operate like print
391 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
393 VM_Warning(prog, "tried to centerprint to a non-client\n");
397 client = svs.clients + entnum-1;
398 if (!client->netconnection)
401 MSG_WriteChar(&client->netconnection->message,svc_print);
402 MSG_WriteString(&client->netconnection->message, string);
410 single print to a specific client
412 centerprint(clientent, value)
415 static void VM_SV_centerprint(prvm_prog_t *prog)
419 char string[VM_STRINGTEMP_LENGTH];
421 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
423 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
425 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
427 VM_Warning(prog, "tried to centerprint to a non-client\n");
431 client = svs.clients + entnum-1;
432 if (!client->netconnection)
435 VM_VarString(prog, 1, string, sizeof(string));
436 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
437 MSG_WriteString(&client->netconnection->message, string);
444 particle(origin, color, count)
447 static void VM_SV_particle(prvm_prog_t *prog)
453 VM_SAFEPARMCOUNT(4, VM_SV_particle);
455 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
456 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
457 color = (int)PRVM_G_FLOAT(OFS_PARM2);
458 count = (int)PRVM_G_FLOAT(OFS_PARM3);
459 SV_StartParticle (org, dir, color, count);
469 static void VM_SV_ambientsound(prvm_prog_t *prog)
473 prvm_vec_t vol, attenuation;
476 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
478 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
479 samp = PRVM_G_STRING(OFS_PARM1);
480 vol = PRVM_G_FLOAT(OFS_PARM2);
481 attenuation = PRVM_G_FLOAT(OFS_PARM3);
483 // check to see if samp was properly precached
484 soundnum = SV_SoundIndex(samp, 1);
492 if(sv.protocol == PROTOCOL_NEHAHRABJP)
495 // add an svc_spawnambient command to the level signon packet
498 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
500 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
502 MSG_WriteVector(&sv.signon, pos, sv.protocol);
504 if (large || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
505 MSG_WriteShort (&sv.signon, soundnum);
507 MSG_WriteByte (&sv.signon, soundnum);
509 MSG_WriteByte (&sv.signon, (int)(vol*255));
510 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
518 Each entity can have eight independant sound sources, like voice,
521 Channel 0 is an auto-allocate channel, the others override anything
522 already running on that entity/channel pair.
524 An attenuation of 0 will play full volume everywhere in the level.
525 Larger attenuations will drop off.
527 void(entity e, float chan, string samp, float volume[, float atten[, float pitchchange[, float flags]]]) sound (QUAKE)
530 static void VM_SV_sound(prvm_prog_t *prog)
534 prvm_edict_t *entity;
540 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
542 entity = PRVM_G_EDICT(OFS_PARM0);
543 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
544 sample = PRVM_G_STRING(OFS_PARM2);
545 nvolume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
548 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
552 attenuation = PRVM_G_FLOAT(OFS_PARM4);
556 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
561 if(channel >= 8 && channel <= 15) // weird QW feature
563 flags |= CHANNELFLAG_RELIABLE;
569 // LadyHavoc: we only let the qc set certain flags, others are off-limits
570 flags = (int)PRVM_G_FLOAT(OFS_PARM6) & (CHANNELFLAG_RELIABLE | CHANNELFLAG_FORCELOOP | CHANNELFLAG_PAUSED | CHANNELFLAG_FULLVOLUME);
573 if (nvolume < 0 || nvolume > 255)
575 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
579 if (attenuation < 0 || attenuation > 4)
581 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
585 channel = CHAN_USER2ENGINE(channel);
587 if (!IS_CHAN(channel))
589 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
593 SV_StartSound (entity, channel, sample, nvolume, attenuation, flags & CHANNELFLAG_RELIABLE, pitchchange);
600 Follows the same logic as VM_SV_sound, except instead of
601 an entity, an origin for the sound is provided, and channel
602 is omitted (since no entity is being tracked).
606 static void VM_SV_pointsound(prvm_prog_t *prog)
614 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
616 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
617 sample = PRVM_G_STRING(OFS_PARM1);
618 nvolume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
619 attenuation = PRVM_G_FLOAT(OFS_PARM3);
620 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
622 if (nvolume < 0 || nvolume > 255)
624 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
628 if (attenuation < 0 || attenuation > 4)
630 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
634 SV_StartPointSound (org, sample, nvolume, attenuation, pitchchange);
641 Used for use tracing and shot targeting
642 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
643 if the tryents flag is set.
645 traceline (vector1, vector2, movetype, ignore)
648 static void VM_SV_traceline(prvm_prog_t *prog)
655 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
657 prog->xfunction->builtinsprofile += 30;
659 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
660 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), v2);
661 move = (int)PRVM_G_FLOAT(OFS_PARM2);
662 ent = PRVM_G_EDICT(OFS_PARM3);
664 if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_IS_NAN(v2[2]))
665 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));
667 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtracelinelength.value);
669 VM_SetTraceGlobals(prog, &trace);
677 Used for use tracing and shot targeting
678 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
679 if the tryents flag is set.
681 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
684 // LadyHavoc: added this for my own use, VERY useful, similar to traceline
685 static void VM_SV_tracebox(prvm_prog_t *prog)
687 vec3_t v1, v2, m1, m2;
692 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
694 prog->xfunction->builtinsprofile += 30;
696 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
697 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), m1);
698 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), m2);
699 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), v2);
700 move = (int)PRVM_G_FLOAT(OFS_PARM4);
701 ent = PRVM_G_EDICT(OFS_PARM5);
703 if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_IS_NAN(v2[2]))
704 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));
706 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtraceboxlength.value);
708 VM_SetTraceGlobals(prog, &trace);
711 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
715 vec3_t move, end, tossentorigin, tossentmins, tossentmaxs;
716 vec3_t original_origin;
717 vec3_t original_velocity;
718 vec3_t original_angles;
719 vec3_t original_avelocity;
722 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
723 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
724 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
725 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
727 gravity = PRVM_serveredictfloat(tossent, gravity);
730 gravity *= sv_gravity.value * 0.025;
732 for (i = 0;i < 200;i++) // LadyHavoc: sanity check; never trace more than 10 seconds
734 SV_CheckVelocity (tossent);
735 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
736 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
737 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
738 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
739 VectorCopy(PRVM_serveredictvector(tossent, origin), tossentorigin);
740 VectorCopy(PRVM_serveredictvector(tossent, mins), tossentmins);
741 VectorCopy(PRVM_serveredictvector(tossent, maxs), tossentmaxs);
742 trace = SV_TraceBox(tossentorigin, tossentmins, tossentmaxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent), 0, 0, collision_extendmovelength.value);
743 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
744 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
746 if (trace.fraction < 1)
750 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
751 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
752 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
753 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
758 static void VM_SV_tracetoss(prvm_prog_t *prog)
762 prvm_edict_t *ignore;
764 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
766 prog->xfunction->builtinsprofile += 600;
768 ent = PRVM_G_EDICT(OFS_PARM0);
769 if (ent == prog->edicts)
771 VM_Warning(prog, "tracetoss: can not use world entity\n");
774 ignore = PRVM_G_EDICT(OFS_PARM1);
776 trace = SV_Trace_Toss(prog, ent, ignore);
778 VM_SetTraceGlobals(prog, &trace);
781 //============================================================================
783 static int checkpvsbytes;
784 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
786 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
792 // cycle to the next one
794 check = bound(1, check, svs.maxclients);
795 if (check == svs.maxclients)
803 prog->xfunction->builtinsprofile++;
805 if (i == svs.maxclients+1)
807 // look up the client's edict
808 ent = PRVM_EDICT_NUM(i);
809 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
810 if (i != check && (ent->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
812 // found a valid client (possibly the same one again)
816 // get the PVS for the entity
817 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
819 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
820 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
829 Returns a client (or object that has a client enemy) that would be a
832 If there is more than one valid option, they are cycled each frame
834 If (self.origin + self.viewofs) is not in the PVS of the current target,
835 it is not returned at all.
840 int c_invis, c_notvis;
841 static void VM_SV_checkclient(prvm_prog_t *prog)
843 prvm_edict_t *ent, *self;
846 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
848 // find a new check if on a new frame
849 if (sv.time - sv.lastchecktime >= 0.1)
851 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
852 sv.lastchecktime = sv.time;
855 // return check if it might be visible
856 ent = PRVM_EDICT_NUM(sv.lastcheck);
857 if (ent->free || PRVM_serveredictfloat(ent, health) <= 0)
859 VM_RETURN_EDICT(prog->edicts);
863 // if current entity can't possibly see the check entity, return 0
864 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
865 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
866 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
869 VM_RETURN_EDICT(prog->edicts);
873 // might be able to see it
875 VM_RETURN_EDICT(ent);
878 //============================================================================
884 Checks if an entity is in a point's PVS.
885 Should be fast but can be inexact.
887 float checkpvs(vector viewpos, entity viewee) = #240;
890 static void VM_SV_checkpvs(prvm_prog_t *prog)
892 vec3_t viewpos, absmin, absmax;
893 prvm_edict_t *viewee;
898 unsigned char fatpvs[MAX_MAP_LEAFS/8];
901 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
902 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
903 viewee = PRVM_G_EDICT(OFS_PARM1);
907 VM_Warning(prog, "checkpvs: can not check free entity\n");
908 PRVM_G_FLOAT(OFS_RETURN) = 4;
913 if(!sv.worldmodel || !sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
915 // no PVS support on this worldmodel... darn
916 PRVM_G_FLOAT(OFS_RETURN) = 3;
919 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
922 // viewpos isn't in any PVS... darn
923 PRVM_G_FLOAT(OFS_RETURN) = 2;
926 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
927 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
928 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, absmin, absmax);
930 // using fat PVS like FTEQW does (slow)
931 if(!sv.worldmodel || !sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
933 // no PVS support on this worldmodel... darn
934 PRVM_G_FLOAT(OFS_RETURN) = 3;
937 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
940 // viewpos isn't in any PVS... darn
941 PRVM_G_FLOAT(OFS_RETURN) = 2;
944 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
945 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
946 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, absmin, absmax);
955 Sends text over to the client's execution buffer
957 stuffcmd (clientent, value, ...)
960 static void VM_SV_stuffcmd(prvm_prog_t *prog)
964 char string[VM_STRINGTEMP_LENGTH];
966 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
968 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
969 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
971 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
975 VM_VarString(prog, 1, string, sizeof(string));
978 host_client = svs.clients + entnum-1;
979 SV_ClientCommands ("%s", string);
987 Returns a chain of entities that have origins within a spherical area
989 findradius (origin, radius)
992 static void VM_SV_findradius(prvm_prog_t *prog)
994 prvm_edict_t *ent, *chain;
995 vec_t radius, radius2;
996 vec3_t org, eorg, mins, maxs;
999 static prvm_edict_t *touchedicts[MAX_EDICTS];
1002 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
1005 chainfield = PRVM_G_INT(OFS_PARM2);
1007 chainfield = prog->fieldoffsets.chain;
1009 prog->error_cmd("VM_SV_findradius: %s doesnt have the specified chain field !", prog->name);
1011 chain = (prvm_edict_t *)prog->edicts;
1013 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1014 radius = PRVM_G_FLOAT(OFS_PARM1);
1015 radius2 = radius * radius;
1017 mins[0] = org[0] - (radius + 1);
1018 mins[1] = org[1] - (radius + 1);
1019 mins[2] = org[2] - (radius + 1);
1020 maxs[0] = org[0] + (radius + 1);
1021 maxs[1] = org[1] + (radius + 1);
1022 maxs[2] = org[2] + (radius + 1);
1023 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1024 if (numtouchedicts > MAX_EDICTS)
1026 // this never happens
1027 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1028 numtouchedicts = MAX_EDICTS;
1030 for (i = 0;i < numtouchedicts;i++)
1032 ent = touchedicts[i];
1033 prog->xfunction->builtinsprofile++;
1034 // Quake did not return non-solid entities but darkplaces does
1035 // (note: this is the reason you can't blow up fallen zombies)
1036 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1038 // LadyHavoc: compare against bounding box rather than center so it
1039 // doesn't miss large objects, and use DotProduct instead of Length
1040 // for a major speedup
1041 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1042 if (sv_gameplayfix_findradiusdistancetobox.integer)
1044 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1045 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1046 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1049 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1050 if (DotProduct(eorg, eorg) < radius2)
1052 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1057 VM_RETURN_EDICT(chain);
1064 Returns a chain of entities that are touching a box (a simpler findradius); supports DP_QC_FINDCHAIN_TOFIELD
1066 findbox (mins, maxs)
1069 static void VM_SV_findbox(prvm_prog_t *prog)
1071 prvm_edict_t *chain;
1072 int i, numtouchedicts;
1073 static prvm_edict_t *touchedicts[MAX_EDICTS];
1076 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findbox);
1079 chainfield = PRVM_G_INT(OFS_PARM2);
1081 chainfield = prog->fieldoffsets.chain;
1083 prog->error_cmd("VM_SV_findbox: %s doesnt have the specified chain field !", prog->name);
1085 chain = (prvm_edict_t *)prog->edicts;
1087 numtouchedicts = SV_EntitiesInBox(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), MAX_EDICTS, touchedicts);
1088 if (numtouchedicts > MAX_EDICTS)
1090 // this never happens
1091 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1092 numtouchedicts = MAX_EDICTS;
1094 for (i = 0; i < numtouchedicts; ++i)
1096 prog->xfunction->builtinsprofile++;
1097 PRVM_EDICTFIELDEDICT(touchedicts[i], chainfield) = PRVM_EDICT_TO_PROG(chain);
1098 chain = touchedicts[i];
1101 VM_RETURN_EDICT(chain);
1104 static void VM_SV_precache_sound(prvm_prog_t *prog)
1106 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1107 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1110 static void VM_SV_precache_model(prvm_prog_t *prog)
1112 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1113 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1114 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1121 float(float yaw, float dist[, settrace]) walkmove
1124 static void VM_SV_walkmove(prvm_prog_t *prog)
1133 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1135 // assume failure if it returns early
1136 PRVM_G_FLOAT(OFS_RETURN) = 0;
1138 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1139 if (ent == prog->edicts)
1141 VM_Warning(prog, "walkmove: can not modify world entity\n");
1146 VM_Warning(prog, "walkmove: can not modify free entity\n");
1149 yaw = PRVM_G_FLOAT(OFS_PARM0);
1150 dist = PRVM_G_FLOAT(OFS_PARM1);
1151 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1153 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1156 yaw = yaw*M_PI*2 / 360;
1158 move[0] = cos(yaw)*dist;
1159 move[1] = sin(yaw)*dist;
1162 // save program state, because SV_movestep may call other progs
1163 oldf = prog->xfunction;
1164 oldself = PRVM_serverglobaledict(self);
1166 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1169 // restore program state
1170 prog->xfunction = oldf;
1171 PRVM_serverglobaledict(self) = oldself;
1182 static void VM_SV_droptofloor(prvm_prog_t *prog)
1185 vec3_t end, entorigin, entmins, entmaxs;
1188 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1190 // assume failure if it returns early
1191 PRVM_G_FLOAT(OFS_RETURN) = 0;
1193 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1194 if (ent == prog->edicts)
1196 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1201 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1205 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1206 if (sv.worldmodel->brush.isq3bsp)
1208 else if (sv.worldmodel->brush.isq2bsp)
1211 end[2] -= 256; // Quake, QuakeWorld
1213 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1215 int n = PHYS_NudgeOutOfSolid(prog, ent);
1217 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)));
1219 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)));
1222 /* bones_was_here: not using SV_GenericHitSuperContentsMask(ent) anymore because it was setting:
1223 * items: SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY
1224 * monsters: SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP
1225 * explobox: SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE
1226 * which caused (startsolid == true) when, for example, a health was touching a monster.
1227 * Changing MOVE_NORMAL also fixes that, but other engines are using MOVE_NORMAL here.
1229 VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
1230 VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
1231 VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
1232 trace = SV_TraceBox(entorigin, entmins, entmaxs, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID, 0, 0, collision_extendmovelength.value);
1233 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1236 VectorSet(offset, 0.5f * (PRVM_serveredictvector(ent, mins)[0] + PRVM_serveredictvector(ent, maxs)[0]), 0.5f * (PRVM_serveredictvector(ent, mins)[1] + PRVM_serveredictvector(ent, maxs)[1]), PRVM_serveredictvector(ent, mins)[2]);
1237 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1238 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID, 0, 0, collision_extendmovelength.value);
1239 VectorSubtract(trace.endpos, offset, trace.endpos);
1240 if (trace.startsolid)
1242 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)));
1244 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1245 PRVM_serveredictedict(ent, groundentity) = 0;
1246 PRVM_G_FLOAT(OFS_RETURN) = 1;
1248 else if (trace.fraction < 1)
1250 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)));
1251 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1252 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1253 PHYS_NudgeOutOfSolid(prog, ent);
1255 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1256 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1257 PRVM_G_FLOAT(OFS_RETURN) = 1;
1258 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1259 ent->priv.server->suspendedinairflag = true;
1264 if (trace.startsolid)
1265 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);
1267 if (!trace.allsolid && trace.fraction < 1)
1269 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1271 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1272 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1273 PRVM_G_FLOAT(OFS_RETURN) = 1;
1274 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1275 ent->priv.server->suspendedinairflag = true;
1284 void(float style, string value) lightstyle
1287 static void VM_SV_lightstyle(prvm_prog_t *prog)
1294 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1296 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1297 val = PRVM_G_STRING(OFS_PARM1);
1299 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1300 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1303 // change the string in sv
1304 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1306 // send message to all clients on this server
1307 if (sv.state != ss_active)
1310 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1312 if (client->active && client->netconnection)
1314 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1315 MSG_WriteChar (&client->netconnection->message,style);
1316 MSG_WriteString (&client->netconnection->message, val);
1326 static void VM_SV_checkbottom(prvm_prog_t *prog)
1328 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1329 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1337 static void VM_SV_pointcontents(prvm_prog_t *prog)
1340 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1341 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point);
1342 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(SV_PointSuperContents(point));
1349 Pick a vector for the player to shoot along
1350 vector aim(entity, missilespeed)
1353 static void VM_SV_aim(prvm_prog_t *prog)
1355 prvm_edict_t *ent, *check, *bestent;
1356 vec3_t start, dir, end, bestdir;
1359 float dist, bestdist;
1362 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1364 // assume failure if it returns early
1365 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1366 // if sv_aim is so high it can't possibly accept anything, skip out early
1367 if (sv_aim.value >= 1)
1370 ent = PRVM_G_EDICT(OFS_PARM0);
1371 if (ent == prog->edicts)
1373 VM_Warning(prog, "aim: can not use world entity\n");
1378 VM_Warning(prog, "aim: can not use free entity\n");
1381 //speed = PRVM_G_FLOAT(OFS_PARM1);
1383 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1386 // try sending a trace straight
1387 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1388 VectorMA (start, 2048, dir, end);
1389 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1390 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1391 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1393 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1398 // try all possible entities
1399 VectorCopy (dir, bestdir);
1400 bestdist = sv_aim.value;
1403 check = PRVM_NEXT_EDICT(prog->edicts);
1404 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1406 prog->xfunction->builtinsprofile++;
1407 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1411 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1412 continue; // don't aim at teammate
1413 for (j=0 ; j<3 ; j++)
1414 end[j] = PRVM_serveredictvector(check, origin)[j]
1415 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1416 VectorSubtract (end, start, dir);
1417 VectorNormalize (dir);
1418 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1419 if (dist < bestdist)
1420 continue; // to far to turn
1421 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1422 if (tr.ent == check)
1423 { // can shoot at this one
1431 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1432 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1433 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1435 VectorNormalize (end);
1436 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1440 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1445 ===============================================================================
1449 ===============================================================================
1452 #define MSG_BROADCAST 0 // unreliable to all
1453 #define MSG_ONE 1 // reliable to one (msg_entity)
1454 #define MSG_ALL 2 // reliable to all
1455 #define MSG_INIT 3 // write to the init string
1456 #define MSG_ENTITY 5
1458 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1464 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1468 return &sv.datagram;
1471 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1472 entnum = PRVM_NUM_FOR_EDICT(ent);
1473 if (entnum < 1 || entnum > svs.maxclients)
1475 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1476 return &sv.reliable_datagram;
1478 else if (!svs.clients[entnum-1].active)
1480 VM_Warning(prog, "WriteDest: tried to write to a disconnected client\n");
1481 return &sv.reliable_datagram;
1483 else if (!svs.clients[entnum-1].netconnection)
1485 VM_Warning(prog, "WriteDest: tried to write to a bot client\n");
1486 return &sv.reliable_datagram;
1489 return &svs.clients[entnum-1].netconnection->message;
1492 VM_Warning(prog, "WriteDest: bad destination\n");
1494 return &sv.reliable_datagram;
1500 return sv.writeentitiestoclient_msg;
1506 static void VM_SV_WriteByte(prvm_prog_t *prog)
1508 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1509 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1512 static void VM_SV_WriteChar(prvm_prog_t *prog)
1514 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1515 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1518 static void VM_SV_WriteShort(prvm_prog_t *prog)
1520 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1521 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1524 static void VM_SV_WriteLong(prvm_prog_t *prog)
1526 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1527 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1530 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1532 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1533 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1536 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1538 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1539 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1542 static void VM_SV_WriteString(prvm_prog_t *prog)
1544 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1545 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1548 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1550 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1551 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1555 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1557 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1558 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1561 // writes a picture as at most size bytes of data
1563 // IMGNAME \0 SIZE(short) IMGDATA
1564 // if failed to read/compress:
1566 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1567 static void VM_SV_WritePicture(prvm_prog_t *prog)
1569 const char *imgname;
1573 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1575 imgname = PRVM_G_STRING(OFS_PARM1);
1576 size = (size_t) PRVM_G_FLOAT(OFS_PARM2);
1580 MSG_WriteString(WriteDest(prog), imgname);
1581 if(Image_Compress(imgname, size, &buf, &size))
1584 MSG_WriteShort(WriteDest(prog), (int)size);
1585 SZ_Write(WriteDest(prog), (unsigned char *) buf, (int)size);
1590 MSG_WriteShort(WriteDest(prog), 0);
1594 //////////////////////////////////////////////////////////
1596 static void VM_SV_makestatic(prvm_prog_t *prog)
1601 // allow 0 parameters due to an id1 qc bug in which this function is used
1602 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1603 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1605 if (prog->argc >= 1)
1606 ent = PRVM_G_EDICT(OFS_PARM0);
1608 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1609 if (ent == prog->edicts)
1611 VM_Warning(prog, "makestatic: can not modify world entity\n");
1616 VM_Warning(prog, "makestatic: can not modify free entity\n");
1621 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1624 if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1626 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1627 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1628 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1632 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1633 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1634 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1638 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1639 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1640 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1643 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1644 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1645 for (i=0 ; i<3 ; i++)
1647 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1648 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1651 // throw the entity away now
1652 PRVM_ED_Free(prog, ent);
1655 //=============================================================================
1662 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1668 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1670 ent = PRVM_G_EDICT(OFS_PARM0);
1671 i = PRVM_NUM_FOR_EDICT(ent);
1672 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1674 Con_Print("tried to setspawnparms on a non-client\n");
1678 // copy spawn parms out of the client_t
1679 client = svs.clients + i-1;
1680 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1681 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1688 Returns a color vector indicating the lighting at the requested point.
1690 (Internal Operation note: actually measures the light beneath the point, just like
1691 the model lighting on the client)
1696 static void VM_SV_getlight(prvm_prog_t *prog)
1698 vec3_t ambientcolor, diffusecolor, diffusenormal;
1700 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1701 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
1702 VectorClear(ambientcolor);
1703 VectorClear(diffusecolor);
1704 VectorClear(diffusenormal);
1705 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1706 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1707 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1712 unsigned char type; // 1/2/8 or 0 to indicate unused
1716 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)
1717 static int vm_customstats_last;
1719 void VM_CustomStats_Clear (void)
1721 memset(vm_customstats, 0, sizeof(vm_customstats));
1722 vm_customstats_last = -1;
1725 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1727 prvm_prog_t *prog = SVVM_prog;
1735 for(i=MIN_VM_STAT; i<=vm_customstats_last ;i++)
1737 if(!vm_customstats[i].type)
1739 switch(vm_customstats[i].type)
1741 //string as 16 bytes
1744 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1745 stats[i] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1746 stats[i+1] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1747 stats[i+2] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1748 stats[i+3] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1750 //float field sent as-is
1752 // 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
1753 u.f = PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1756 //integer value of float field
1758 stats[i] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1766 extern cvar_t sv_gameplayfix_customstats;
1768 // void(float index, float type, .void field) SV_AddStat = #232;
1769 // Set up an auto-sent player stat.
1770 // Client's get thier own fields sent to them. Index may not be less than 32.
1771 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1772 // 1: string (4 stats carrying a total of 16 charactures)
1773 // 2: float (one stat, float converted to an integer for transportation)
1774 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1775 static void VM_SV_AddStat(prvm_prog_t *prog)
1779 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1781 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1782 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1783 off = PRVM_G_INT (OFS_PARM2);
1792 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);
1798 VM_Warning(prog, "PF_SV_AddStat: index (%i) may not be less than %i\n", i, MIN_VM_STAT);
1802 if (i >= MAX_CL_STATS)
1804 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);
1808 if (i > (MAX_CL_STATS - 4) && type == 1)
1810 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);
1814 // these are hazardous to override but sort of allowed if one wants to be adventurous... and enjoys warnings.
1815 if (i < MIN_VM_STAT)
1816 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);
1817 else if (i >= MAX_VM_STAT && !sv_gameplayfix_customstats.integer)
1818 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);
1819 else if (i > (MAX_VM_STAT - 4) && type == 1 && !sv_gameplayfix_customstats.integer)
1820 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);
1822 vm_customstats[i].type = type;
1823 vm_customstats[i].fieldoffset = off;
1824 if(vm_customstats_last < i)
1825 vm_customstats_last = i;
1832 copies data from one entity to another
1834 copyentity(src, dst)
1837 static void VM_SV_copyentity(prvm_prog_t *prog)
1839 prvm_edict_t *in, *out;
1840 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1841 in = PRVM_G_EDICT(OFS_PARM0);
1842 if (in == prog->edicts)
1844 VM_Warning(prog, "copyentity: can not read world entity\n");
1849 VM_Warning(prog, "copyentity: can not read free entity\n");
1852 out = PRVM_G_EDICT(OFS_PARM1);
1853 if (out == prog->edicts)
1855 VM_Warning(prog, "copyentity: can not modify world entity\n");
1860 VM_Warning(prog, "copyentity: can not modify free entity\n");
1863 memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
1873 sets the color of a client and broadcasts the update to all connected clients
1875 setcolor(clientent, value)
1878 static void VM_SV_setcolor(prvm_prog_t *prog)
1883 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1884 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1885 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1887 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1889 Con_Print("tried to setcolor a non-client\n");
1893 client = svs.clients + entnum-1;
1896 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1897 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1900 if (client->old_colors != client->colors)
1902 client->old_colors = client->colors;
1903 // send notification to all clients
1904 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1905 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1906 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1914 effect(origin, modelname, startframe, framecount, framerate)
1917 static void VM_SV_effect(prvm_prog_t *prog)
1922 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1923 s = PRVM_G_STRING(OFS_PARM1);
1926 VM_Warning(prog, "effect: no model specified\n");
1930 i = SV_ModelIndex(s, 1);
1933 VM_Warning(prog, "effect: model not precached\n");
1937 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1939 VM_Warning(prog, "effect: framecount < 1\n");
1943 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1945 VM_Warning(prog, "effect: framerate < 1\n");
1949 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1950 SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1953 static void VM_SV_te_blood(prvm_prog_t *prog)
1955 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1956 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1958 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1959 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1965 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1966 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1967 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1969 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1970 SV_FlushBroadcastMessages();
1973 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1975 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1976 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1978 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1979 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1983 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1985 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1989 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1991 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1992 SV_FlushBroadcastMessages();
1995 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1997 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1998 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1999 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2001 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2002 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2005 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
2006 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
2007 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
2008 SV_FlushBroadcastMessages();
2011 static void VM_SV_te_particlecube(prvm_prog_t *prog)
2013 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
2014 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2016 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2017 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2019 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2020 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2021 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2023 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2024 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2025 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2028 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2029 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2031 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2033 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2034 // gravity true/false
2035 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
2037 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
2038 SV_FlushBroadcastMessages();
2041 static void VM_SV_te_particlerain(prvm_prog_t *prog)
2043 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
2044 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2046 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2047 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2049 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2050 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2054 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2055 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2058 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2059 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2061 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2063 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2064 SV_FlushBroadcastMessages();
2067 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
2069 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
2070 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2072 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2073 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2075 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2076 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2077 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2079 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2080 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2081 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2083 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2084 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2085 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2087 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2089 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2090 SV_FlushBroadcastMessages();
2093 static void VM_SV_te_spark(prvm_prog_t *prog)
2095 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
2096 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2098 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2099 MSG_WriteByte(&sv.datagram, TE_SPARK);
2101 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2102 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2103 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2105 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2106 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2107 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2109 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2110 SV_FlushBroadcastMessages();
2113 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2115 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2116 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2117 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2119 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2120 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2121 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2122 SV_FlushBroadcastMessages();
2125 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2127 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2128 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2129 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2131 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2132 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2133 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2134 SV_FlushBroadcastMessages();
2137 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2139 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2140 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2141 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2143 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2144 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2145 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2146 SV_FlushBroadcastMessages();
2149 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2151 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2152 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2153 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2155 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2156 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2157 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2158 SV_FlushBroadcastMessages();
2161 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2163 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2164 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2165 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2167 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2168 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2169 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2170 SV_FlushBroadcastMessages();
2173 static void VM_SV_te_customflash(prvm_prog_t *prog)
2175 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2176 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2178 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2179 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2181 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2182 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2183 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2185 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2187 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2189 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2190 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2191 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2192 SV_FlushBroadcastMessages();
2195 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2197 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2198 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2199 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2201 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2202 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2203 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2204 SV_FlushBroadcastMessages();
2207 static void VM_SV_te_spike(prvm_prog_t *prog)
2209 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2210 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2211 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2213 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2214 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2215 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2216 SV_FlushBroadcastMessages();
2219 static void VM_SV_te_superspike(prvm_prog_t *prog)
2221 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2222 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2223 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2225 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2226 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2227 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2228 SV_FlushBroadcastMessages();
2231 static void VM_SV_te_explosion(prvm_prog_t *prog)
2233 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2234 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2235 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2237 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2238 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2239 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2240 SV_FlushBroadcastMessages();
2243 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2245 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2246 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2247 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2249 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2250 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2251 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2252 SV_FlushBroadcastMessages();
2255 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2257 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2258 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2259 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2261 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2262 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2263 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2264 SV_FlushBroadcastMessages();
2267 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2269 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2270 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2271 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2273 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2274 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2275 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2276 SV_FlushBroadcastMessages();
2279 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2281 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2282 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2283 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2285 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2286 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2287 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2288 SV_FlushBroadcastMessages();
2291 static void VM_SV_te_teleport(prvm_prog_t *prog)
2293 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2294 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2295 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2297 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2298 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2299 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2300 SV_FlushBroadcastMessages();
2303 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2305 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2306 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2307 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2309 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2310 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2311 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2313 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2314 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2315 SV_FlushBroadcastMessages();
2318 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2320 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2321 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2322 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2324 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2326 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2327 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2328 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2330 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2331 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2332 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2333 SV_FlushBroadcastMessages();
2336 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2338 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2339 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2340 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2342 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2344 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2345 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2346 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2348 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2349 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2350 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2351 SV_FlushBroadcastMessages();
2354 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2356 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2357 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2358 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2360 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2362 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2363 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2364 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2366 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2367 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2368 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2369 SV_FlushBroadcastMessages();
2372 static void VM_SV_te_beam(prvm_prog_t *prog)
2374 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2375 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2376 MSG_WriteByte(&sv.datagram, TE_BEAM);
2378 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2380 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2381 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2382 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2384 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2385 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2386 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2387 SV_FlushBroadcastMessages();
2390 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2392 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2393 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2394 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2395 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2396 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2397 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2398 SV_FlushBroadcastMessages();
2401 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2403 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2404 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2405 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2407 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2408 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2409 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2411 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2412 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2413 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2415 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2416 SV_FlushBroadcastMessages();
2419 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2420 //this function originally written by KrimZon, made shorter by LadyHavoc
2421 static void VM_SV_clientcommand(prvm_prog_t *prog)
2423 client_t *temp_client;
2425 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2427 //find client for this entity
2428 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2429 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2431 Con_Print("PF_clientcommand: entity is not a client\n");
2435 temp_client = host_client;
2436 host_client = svs.clients + i;
2437 Cmd_ExecuteString(cmd_serverfromclient, PRVM_G_STRING(OFS_PARM1), src_client, true);
2438 host_client = temp_client;
2441 //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)
2442 static void VM_SV_setattachment(prvm_prog_t *prog)
2444 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2445 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2446 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2449 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2451 if (e == prog->edicts)
2453 VM_Warning(prog, "setattachment: can not modify world entity\n");
2458 VM_Warning(prog, "setattachment: can not modify free entity\n");
2462 if (tagentity == NULL)
2463 tagentity = prog->edicts;
2467 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2469 model = SV_GetModelFromEdict(tagentity);
2472 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2474 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);
2477 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));
2480 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2481 PRVM_serveredictfloat(e, tag_index) = tagindex;
2484 /////////////////////////////////////////
2485 // DP_MD3_TAGINFO extension coded by VorteX
2487 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2491 i = (int)PRVM_serveredictfloat(e, modelindex);
2492 if (i < 1 || i >= MAX_MODELS)
2495 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2498 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2505 Matrix4x4_CreateIdentity(tag_localmatrix);
2507 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2509 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2520 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qbool viewmatrix)
2523 float pitchsign = 1;
2525 scale = PRVM_serveredictfloat(ent, scale);
2530 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);
2533 pitchsign = SV_GetPitchSign(prog, ent);
2534 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);
2538 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2541 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2543 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2544 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2545 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2546 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2548 *out = identitymatrix;
2552 // Warnings/errors code:
2553 // 0 - normal (everything all-right)
2556 // 3 - null or non-precached model
2557 // 4 - no tags with requested index
2558 // 5 - runaway loop at attachment chain
2559 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2562 int modelindex, attachloop;
2563 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2566 *out = identitymatrix; // warnings and errors return identical matrix
2568 if (ent == prog->edicts)
2573 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2574 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2577 model = SV_GetModelByIndex(modelindex);
2579 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2580 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2581 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2583 tagmatrix = identitymatrix;
2584 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2588 if (attachloop >= 256) // prevent runaway looping
2590 // apply transformation by child's tagindex on parent entity and then
2591 // by parent entity itself
2592 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2593 if (ret && attachloop == 0)
2595 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2596 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2597 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2598 // next iteration we process the parent entity
2599 if (PRVM_serveredictedict(ent, tag_entity))
2601 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2602 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2609 // RENDER_VIEWMODEL magic
2610 if (PRVM_serveredictedict(ent, viewmodelforclient))
2612 Matrix4x4_Copy(&tagmatrix, out);
2613 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2615 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2616 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2621 //float(entity ent, string tagname) gettagindex;
2623 static void VM_SV_gettagindex(prvm_prog_t *prog)
2626 const char *tag_name;
2629 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2631 ent = PRVM_G_EDICT(OFS_PARM0);
2632 tag_name = PRVM_G_STRING(OFS_PARM1);
2634 if (ent == prog->edicts)
2636 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2641 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2646 if (!SV_GetModelFromEdict(ent))
2647 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2650 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2652 if(developer_extra.integer)
2653 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2655 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2658 //vector(entity ent, float tagindex) gettaginfo;
2659 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2663 matrix4x4_t tag_matrix;
2664 matrix4x4_t tag_localmatrix;
2666 const char *tagname;
2668 vec3_t forward, left, up, origin;
2669 const model_t *model;
2671 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2673 e = PRVM_G_EDICT(OFS_PARM0);
2674 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2676 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2677 Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
2678 VectorCopy(forward, PRVM_serverglobalvector(v_forward));
2679 VectorNegate(left, PRVM_serverglobalvector(v_right));
2680 VectorCopy(up, PRVM_serverglobalvector(v_up));
2681 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2682 model = SV_GetModelFromEdict(e);
2683 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2684 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2685 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2686 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2687 Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
2689 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2690 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2691 VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
2692 VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
2693 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2694 VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset));
2699 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2702 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2705 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2708 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2711 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2716 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2717 static void VM_SV_dropclient(prvm_prog_t *prog)
2720 client_t *oldhostclient;
2721 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2722 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2723 if (clientnum < 0 || clientnum >= svs.maxclients)
2725 VM_Warning(prog, "dropclient: not a client\n");
2728 if (!svs.clients[clientnum].active)
2730 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2733 oldhostclient = host_client;
2734 host_client = svs.clients + clientnum;
2735 SV_DropClient(false, "Client dropped");
2736 host_client = oldhostclient;
2739 //entity() spawnclient (DP_SV_BOTCLIENT)
2740 static void VM_SV_spawnclient(prvm_prog_t *prog)
2744 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2745 prog->xfunction->builtinsprofile += 2;
2747 for (i = 0;i < svs.maxclients;i++)
2749 if (!svs.clients[i].active)
2751 prog->xfunction->builtinsprofile += 100;
2752 SV_ConnectClient (i, NULL);
2753 // this has to be set or else ClientDisconnect won't be called
2754 // we assume the qc will call ClientConnect...
2755 svs.clients[i].clientconnectcalled = true;
2756 ed = PRVM_EDICT_NUM(i + 1);
2760 VM_RETURN_EDICT(ed);
2763 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2764 static void VM_SV_clienttype(prvm_prog_t *prog)
2767 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2768 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2769 if (clientnum < 0 || clientnum >= svs.maxclients)
2770 PRVM_G_FLOAT(OFS_RETURN) = 3; // CLIENTTYPE_NOTACLIENT
2771 else if (!svs.clients[clientnum].active)
2772 PRVM_G_FLOAT(OFS_RETURN) = 0; // CLIENTTYPE_DISCONNECTED
2773 else if (svs.clients[clientnum].netconnection)
2774 PRVM_G_FLOAT(OFS_RETURN) = 1; // CLIENTTYPE_REAL
2776 PRVM_G_FLOAT(OFS_RETURN) = 2; // CLIENTTYPE_BOT
2783 string(string key) serverkey
2786 static void VM_SV_serverkey(prvm_prog_t *prog)
2788 char string[VM_STRINGTEMP_LENGTH];
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);
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)
2930 prvm_prog_t *prog = SVVM_prog;
2931 return PRVM_ConsoleCommand(prog, text, &prog->funcoffsets.ConsoleCmd, true, PRVM_EDICT_TO_PROG(sv.world.prog->edicts), sv.time, !(!sv.active || !prog || !prog->loaded), "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);
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 s1, string s2, ...) 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)
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);
3928 if(prog->loaded && PRVM_serverfunction(SV_Shutdown))
3930 func_t s = PRVM_serverfunction(SV_Shutdown);
3931 PRVM_serverglobalfloat(time) = sv.time;
3932 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3933 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");