6 //============================================================================
11 const char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
24 "DP_CSQC_ENTITYWORLDOBJECT "
25 "DP_CSQC_ENTITYMODELLIGHT "
26 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
28 "DP_CSQC_MINFPS_QUALITY "
29 "DP_CSQC_MULTIFRAME_INTERPOLATION "
30 "DP_CSQC_BOXPARTICLES "
31 "DP_CSQC_SPAWNPARTICLE "
32 "DP_CSQC_QUERYRENDERENTITY "
33 "DP_CSQC_ROTATEMOVES "
46 "DP_EF_RESTARTANIM_BIT "
51 "DP_ENT_CUSTOMCOLORMAP "
52 "DP_ENT_EXTERIORMODELTOCLIENT "
55 "DP_ENT_LOWPRECISION "
57 "DP_ENT_TRAILEFFECTNUM "
59 "DP_GFX_EXTERNALTEXTURES "
60 "DP_GFX_EXTERNALTEXTURES_PERMAP "
62 "DP_GFX_MODEL_INTERPOLATION "
63 "DP_GFX_QUAKE3MODELTAGS "
67 "DP_GFX_FONTS_FREETYPE "
69 "DP_FONT_VARIABLEWIDTH "
71 "DP_HALFLIFE_MAP_CVAR "
74 "DP_LIGHTSTYLE_STATICVALUE "
78 "DP_MOVETYPEBOUNCEMISSILE "
79 "DP_MOVETYPEFLYWORLDONLY "
82 "DP_QC_ASINACOSATANATAN2TAN "
88 "DP_QC_CVAR_DEFSTRING "
89 "DP_QC_CVAR_DESCRIPTION "
93 "DP_QC_DIGEST_SHA256 "
98 "DP_QC_EXTRESPONSEPACKET "
100 "DP_QC_FINDCHAINFLAGS "
101 "DP_QC_FINDCHAINFLOAT "
102 "DP_QC_FINDCHAIN_TOFIELD "
108 "DP_QC_GETSURFACETRIANGLE "
109 "DP_QC_GETSURFACEPOINTATTRIBUTE "
111 "DP_QC_GETTAGINFO_BONEPROPERTIES "
113 "DP_QC_GETTIME_CDTRACK "
117 "DP_QC_MULTIPLETEMPSTRINGS "
118 "DP_QC_NUM_FOR_EDICT "
120 "DP_QC_SINCOSSQRTPOW "
123 "DP_QC_STRINGBUFFERS "
124 "DP_QC_STRINGBUFFERS_CVARLIST "
125 "DP_QC_STRINGCOLORFUNCTIONS "
126 "DP_QC_STRING_CASE_FUNCTIONS "
128 "DP_QC_TOKENIZEBYSEPARATOR "
129 "DP_QC_TOKENIZE_CONSOLE "
132 "DP_QC_TRACE_MOVETYPE_HITMODEL "
133 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
134 "DP_QC_UNLIMITEDTEMPSTRINGS "
138 "DP_QC_VECTOANGLES_WITH_ROLL "
139 "DP_QC_VECTORVECTORS "
146 "DP_SKELETONOBJECTS "
147 "DP_SND_DIRECTIONLESSATTNNONE "
149 "DP_SND_SOUND7_WIP1 "
150 "DP_SND_SOUND7_WIP2 "
154 "DP_SND_GETSOUNDTIME "
156 "DP_VIDEO_SUBTITLES "
160 "DP_SV_BOUNCEFACTOR "
161 "DP_SV_CLIENTCAMERA "
162 "DP_SV_CLIENTCOLORS "
165 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
166 "DP_SV_DISCARDABLEDEMO "
167 "DP_SV_DRAWONLYTOCLIENT "
170 "DP_SV_ENTITYCONTENTSTRANSITION "
171 "DP_SV_MODELFLAGS_AS_EFFECTS "
172 "DP_SV_MOVETYPESTEP_LANDEVENT "
174 "DP_SV_NODRAWTOCLIENT "
175 "DP_SV_ONENTITYNOSPAWNFUNCTION "
176 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
178 "DP_SV_PING_PACKETLOSS "
179 "DP_SV_PLAYERPHYSICS "
181 "DP_SV_POINTPARTICLES "
183 "DP_SV_PRECACHEANYTIME "
187 "DP_SV_ROTATINGBMODEL "
191 "DP_SV_SPAWNFUNC_PREFIX "
192 "DP_SV_WRITEPICTURE "
193 "DP_SV_WRITEUNTERMINATEDSTRING "
197 "DP_TE_EXPLOSIONRGB "
199 "DP_TE_PARTICLECUBE "
200 "DP_TE_PARTICLERAIN "
201 "DP_TE_PARTICLESNOW "
203 "DP_TE_QUADEFFECTS1 "
206 "DP_TE_STANDARDEFFECTBUILTINS "
207 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
211 "FTE_CSQC_SKELETONOBJECTS "
214 "KRIMZON_SV_PARSECLIENTCOMMAND "
217 "NEXUIZ_PLAYERMODEL "
219 "PRYDON_CLIENTCURSOR "
220 "TENEBRAE_GFX_DLIGHTS "
223 //"EXT_CSQC " // not ready yet
230 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.
232 setorigin (entity, origin)
235 static void VM_SV_setorigin(prvm_prog_t *prog)
240 VM_SAFEPARMCOUNT(2, VM_setorigin);
242 e = PRVM_G_EDICT(OFS_PARM0);
243 if (e == prog->edicts)
245 VM_Warning(prog, "setorigin: can not modify world entity\n");
248 if (e->priv.server->free)
250 VM_Warning(prog, "setorigin: can not modify free entity\n");
253 org = PRVM_G_VECTOR(OFS_PARM1);
254 VectorCopy (org, PRVM_serveredictvector(e, origin));
255 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
256 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
260 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
261 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qboolean rotate)
265 for (i=0 ; i<3 ; i++)
267 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
269 // set derived values
270 VectorCopy (min, PRVM_serveredictvector(e, mins));
271 VectorCopy (max, PRVM_serveredictvector(e, maxs));
272 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
281 the size box is rotated by the current angle
282 LordHavoc: no it isn't...
284 setsize (entity, minvector, maxvector)
287 static void VM_SV_setsize(prvm_prog_t *prog)
292 VM_SAFEPARMCOUNT(3, VM_setsize);
294 e = PRVM_G_EDICT(OFS_PARM0);
295 if (e == prog->edicts)
297 VM_Warning(prog, "setsize: can not modify world entity\n");
300 if (e->priv.server->free)
302 VM_Warning(prog, "setsize: can not modify free entity\n");
305 min = PRVM_G_VECTOR(OFS_PARM1);
306 max = PRVM_G_VECTOR(OFS_PARM2);
307 SetMinMaxSize(prog, e, min, max, false);
315 setmodel(entity, model)
318 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
319 static void VM_SV_setmodel(prvm_prog_t *prog)
325 VM_SAFEPARMCOUNT(2, VM_setmodel);
327 e = PRVM_G_EDICT(OFS_PARM0);
328 if (e == prog->edicts)
330 VM_Warning(prog, "setmodel: can not modify world entity\n");
333 if (e->priv.server->free)
335 VM_Warning(prog, "setmodel: can not modify free entity\n");
338 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
339 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
340 PRVM_serveredictfloat(e, modelindex) = i;
342 mod = SV_GetModelByIndex(i);
346 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
347 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
349 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
352 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
359 single print to a specific client
361 sprint(clientent, value)
364 static void VM_SV_sprint(prvm_prog_t *prog)
368 char string[VM_STRINGTEMP_LENGTH];
370 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
372 VM_VarString(prog, 1, string, sizeof(string));
374 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
375 // LordHavoc: div0 requested that sprintto world operate like print
382 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
384 VM_Warning(prog, "tried to centerprint to a non-client\n");
388 client = svs.clients + entnum-1;
389 if (!client->netconnection)
392 MSG_WriteChar(&client->netconnection->message,svc_print);
393 MSG_WriteString(&client->netconnection->message, string);
401 single print to a specific client
403 centerprint(clientent, value)
406 static void VM_SV_centerprint(prvm_prog_t *prog)
410 char string[VM_STRINGTEMP_LENGTH];
412 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
414 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
416 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
418 VM_Warning(prog, "tried to centerprint to a non-client\n");
422 client = svs.clients + entnum-1;
423 if (!client->netconnection)
426 VM_VarString(prog, 1, string, sizeof(string));
427 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
428 MSG_WriteString(&client->netconnection->message, string);
435 particle(origin, color, count)
438 static void VM_SV_particle(prvm_prog_t *prog)
444 VM_SAFEPARMCOUNT(4, VM_SV_particle);
446 org = PRVM_G_VECTOR(OFS_PARM0);
447 dir = PRVM_G_VECTOR(OFS_PARM1);
448 color = PRVM_G_FLOAT(OFS_PARM2);
449 count = PRVM_G_FLOAT(OFS_PARM3);
450 SV_StartParticle (org, dir, (int)color, (int)count);
460 static void VM_SV_ambientsound(prvm_prog_t *prog)
464 float vol, attenuation;
467 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
469 pos = PRVM_G_VECTOR (OFS_PARM0);
470 samp = PRVM_G_STRING(OFS_PARM1);
471 vol = PRVM_G_FLOAT(OFS_PARM2);
472 attenuation = PRVM_G_FLOAT(OFS_PARM3);
474 // check to see if samp was properly precached
475 soundnum = SV_SoundIndex(samp, 1);
483 // add an svc_spawnambient command to the level signon packet
486 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
488 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
490 MSG_WriteVector(&sv.signon, pos, sv.protocol);
492 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
493 MSG_WriteShort (&sv.signon, soundnum);
495 MSG_WriteByte (&sv.signon, soundnum);
497 MSG_WriteByte (&sv.signon, (int)(vol*255));
498 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
506 Each entity can have eight independant sound sources, like voice,
509 Channel 0 is an auto-allocate channel, the others override anything
510 already running on that entity/channel pair.
512 An attenuation of 0 will play full volume everywhere in the level.
513 Larger attenuations will drop off.
517 static void VM_SV_sound(prvm_prog_t *prog)
521 prvm_edict_t *entity;
527 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
529 entity = PRVM_G_EDICT(OFS_PARM0);
530 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
531 sample = PRVM_G_STRING(OFS_PARM2);
532 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
535 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
539 attenuation = PRVM_G_FLOAT(OFS_PARM4);
543 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
548 if(channel >= 8 && channel <= 15) // weird QW feature
550 flags |= CHANFLAG_RELIABLE;
555 flags = PRVM_G_FLOAT(OFS_PARM6);
557 if (volume < 0 || volume > 255)
559 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
563 if (attenuation < 0 || attenuation > 4)
565 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
569 channel = CHAN_USER2ENGINE(channel);
571 if (!IS_CHAN(channel))
573 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
577 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE, pitchchange);
584 Follows the same logic as VM_SV_sound, except instead of
585 an entity, an origin for the sound is provided, and channel
586 is omitted (since no entity is being tracked).
590 static void VM_SV_pointsound(prvm_prog_t *prog)
598 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
600 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
601 sample = PRVM_G_STRING(OFS_PARM1);
602 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
603 attenuation = PRVM_G_FLOAT(OFS_PARM3);
604 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
606 if (volume < 0 || volume > 255)
608 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
612 if (attenuation < 0 || attenuation > 4)
614 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
618 SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
625 Used for use tracing and shot targeting
626 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
627 if the tryents flag is set.
629 traceline (vector1, vector2, movetype, ignore)
632 static void VM_SV_traceline(prvm_prog_t *prog)
639 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
641 prog->xfunction->builtinsprofile += 30;
643 v1 = PRVM_G_VECTOR(OFS_PARM0);
644 v2 = PRVM_G_VECTOR(OFS_PARM1);
645 move = (int)PRVM_G_FLOAT(OFS_PARM2);
646 ent = PRVM_G_EDICT(OFS_PARM3);
648 if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
649 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));
651 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
653 VM_SetTraceGlobals(prog, &trace);
661 Used for use tracing and shot targeting
662 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
663 if the tryents flag is set.
665 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
668 // LordHavoc: added this for my own use, VERY useful, similar to traceline
669 static void VM_SV_tracebox(prvm_prog_t *prog)
671 float *v1, *v2, *m1, *m2;
676 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
678 prog->xfunction->builtinsprofile += 30;
680 v1 = PRVM_G_VECTOR(OFS_PARM0);
681 m1 = PRVM_G_VECTOR(OFS_PARM1);
682 m2 = PRVM_G_VECTOR(OFS_PARM2);
683 v2 = PRVM_G_VECTOR(OFS_PARM3);
684 move = (int)PRVM_G_FLOAT(OFS_PARM4);
685 ent = PRVM_G_EDICT(OFS_PARM5);
687 if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
688 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));
690 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
692 VM_SetTraceGlobals(prog, &trace);
695 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
700 vec3_t original_origin;
701 vec3_t original_velocity;
702 vec3_t original_angles;
703 vec3_t original_avelocity;
706 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
707 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
708 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
709 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
711 gravity = PRVM_serveredictfloat(tossent, gravity);
714 gravity *= sv_gravity.value * 0.025;
716 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
718 SV_CheckVelocity (tossent);
719 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
720 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
721 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
722 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
723 trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
724 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
725 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
727 if (trace.fraction < 1)
731 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
732 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
733 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
734 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
739 static void VM_SV_tracetoss(prvm_prog_t *prog)
743 prvm_edict_t *ignore;
745 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
747 prog->xfunction->builtinsprofile += 600;
749 ent = PRVM_G_EDICT(OFS_PARM0);
750 if (ent == prog->edicts)
752 VM_Warning(prog, "tracetoss: can not use world entity\n");
755 ignore = PRVM_G_EDICT(OFS_PARM1);
757 trace = SV_Trace_Toss(prog, ent, ignore);
759 VM_SetTraceGlobals(prog, &trace);
762 //============================================================================
764 static int checkpvsbytes;
765 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
767 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
773 // cycle to the next one
775 check = bound(1, check, svs.maxclients);
776 if (check == svs.maxclients)
784 prog->xfunction->builtinsprofile++;
786 if (i == svs.maxclients+1)
788 // look up the client's edict
789 ent = PRVM_EDICT_NUM(i);
790 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
791 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
793 // found a valid client (possibly the same one again)
797 // get the PVS for the entity
798 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
800 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
801 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
810 Returns a client (or object that has a client enemy) that would be a
813 If there is more than one valid option, they are cycled each frame
815 If (self.origin + self.viewofs) is not in the PVS of the current target,
816 it is not returned at all.
821 int c_invis, c_notvis;
822 static void VM_SV_checkclient(prvm_prog_t *prog)
824 prvm_edict_t *ent, *self;
827 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
829 // find a new check if on a new frame
830 if (sv.time - sv.lastchecktime >= 0.1)
832 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
833 sv.lastchecktime = sv.time;
836 // return check if it might be visible
837 ent = PRVM_EDICT_NUM(sv.lastcheck);
838 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
840 VM_RETURN_EDICT(prog->edicts);
844 // if current entity can't possibly see the check entity, return 0
845 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
846 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
847 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
850 VM_RETURN_EDICT(prog->edicts);
854 // might be able to see it
856 VM_RETURN_EDICT(ent);
859 //============================================================================
865 Checks if an entity is in a point's PVS.
866 Should be fast but can be inexact.
868 float checkpvs(vector viewpos, entity viewee) = #240;
871 static void VM_SV_checkpvs(prvm_prog_t *prog)
874 prvm_edict_t *viewee;
879 unsigned char fatpvs[MAX_MAP_LEAFS/8];
882 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
883 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
884 viewee = PRVM_G_EDICT(OFS_PARM1);
886 if(viewee->priv.server->free)
888 VM_Warning(prog, "checkpvs: can not check free entity\n");
889 PRVM_G_FLOAT(OFS_RETURN) = 4;
894 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
896 // no PVS support on this worldmodel... darn
897 PRVM_G_FLOAT(OFS_RETURN) = 3;
900 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
903 // viewpos isn't in any PVS... darn
904 PRVM_G_FLOAT(OFS_RETURN) = 2;
907 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
909 // using fat PVS like FTEQW does (slow)
910 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
912 // no PVS support on this worldmodel... darn
913 PRVM_G_FLOAT(OFS_RETURN) = 3;
916 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
919 // viewpos isn't in any PVS... darn
920 PRVM_G_FLOAT(OFS_RETURN) = 2;
923 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
932 Sends text over to the client's execution buffer
934 stuffcmd (clientent, value, ...)
937 static void VM_SV_stuffcmd(prvm_prog_t *prog)
941 char string[VM_STRINGTEMP_LENGTH];
943 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
945 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
946 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
948 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
952 VM_VarString(prog, 1, string, sizeof(string));
955 host_client = svs.clients + entnum-1;
956 Host_ClientCommands ("%s", string);
964 Returns a chain of entities that have origins within a spherical area
966 findradius (origin, radius)
969 static void VM_SV_findradius(prvm_prog_t *prog)
971 prvm_edict_t *ent, *chain;
972 vec_t radius, radius2;
973 vec3_t org, eorg, mins, maxs;
976 static prvm_edict_t *touchedicts[MAX_EDICTS];
979 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
982 chainfield = PRVM_G_INT(OFS_PARM2);
984 chainfield = prog->fieldoffsets.chain;
986 prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
988 chain = (prvm_edict_t *)prog->edicts;
990 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
991 radius = PRVM_G_FLOAT(OFS_PARM1);
992 radius2 = radius * radius;
994 mins[0] = org[0] - (radius + 1);
995 mins[1] = org[1] - (radius + 1);
996 mins[2] = org[2] - (radius + 1);
997 maxs[0] = org[0] + (radius + 1);
998 maxs[1] = org[1] + (radius + 1);
999 maxs[2] = org[2] + (radius + 1);
1000 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1001 if (numtouchedicts > MAX_EDICTS)
1003 // this never happens
1004 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1005 numtouchedicts = MAX_EDICTS;
1007 for (i = 0;i < numtouchedicts;i++)
1009 ent = touchedicts[i];
1010 prog->xfunction->builtinsprofile++;
1011 // Quake did not return non-solid entities but darkplaces does
1012 // (note: this is the reason you can't blow up fallen zombies)
1013 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1015 // LordHavoc: compare against bounding box rather than center so it
1016 // doesn't miss large objects, and use DotProduct instead of Length
1017 // for a major speedup
1018 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1019 if (sv_gameplayfix_findradiusdistancetobox.integer)
1021 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1022 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1023 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1026 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1027 if (DotProduct(eorg, eorg) < radius2)
1029 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1034 VM_RETURN_EDICT(chain);
1037 static void VM_SV_precache_sound(prvm_prog_t *prog)
1039 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1040 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1043 static void VM_SV_precache_model(prvm_prog_t *prog)
1045 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1046 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1047 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1054 float(float yaw, float dist[, settrace]) walkmove
1057 static void VM_SV_walkmove(prvm_prog_t *prog)
1066 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1068 // assume failure if it returns early
1069 PRVM_G_FLOAT(OFS_RETURN) = 0;
1071 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1072 if (ent == prog->edicts)
1074 VM_Warning(prog, "walkmove: can not modify world entity\n");
1077 if (ent->priv.server->free)
1079 VM_Warning(prog, "walkmove: can not modify free entity\n");
1082 yaw = PRVM_G_FLOAT(OFS_PARM0);
1083 dist = PRVM_G_FLOAT(OFS_PARM1);
1084 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1086 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1089 yaw = yaw*M_PI*2 / 360;
1091 move[0] = cos(yaw)*dist;
1092 move[1] = sin(yaw)*dist;
1095 // save program state, because SV_movestep may call other progs
1096 oldf = prog->xfunction;
1097 oldself = PRVM_serverglobaledict(self);
1099 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1102 // restore program state
1103 prog->xfunction = oldf;
1104 PRVM_serverglobaledict(self) = oldself;
1115 static void VM_SV_droptofloor(prvm_prog_t *prog)
1121 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1123 // assume failure if it returns early
1124 PRVM_G_FLOAT(OFS_RETURN) = 0;
1126 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1127 if (ent == prog->edicts)
1129 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1132 if (ent->priv.server->free)
1134 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1138 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1141 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1142 if (sv_gameplayfix_unstickentities.integer)
1143 SV_UnstickEntity(ent);
1145 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1146 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1149 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]);
1150 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1151 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1152 VectorSubtract(trace.endpos, offset, trace.endpos);
1153 if (trace.startsolid)
1155 Con_DPrintf("droptofloor at %f %f %f - COULD NOT FIX BADLY PLACED ENTITY\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
1156 if (sv_gameplayfix_unstickentities.integer)
1157 SV_UnstickEntity(ent);
1159 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1160 PRVM_serveredictedict(ent, groundentity) = 0;
1161 PRVM_G_FLOAT(OFS_RETURN) = 1;
1163 else if (trace.fraction < 1)
1165 Con_DPrintf("droptofloor at %f %f %f - FIXED BADLY PLACED ENTITY\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
1166 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1167 if (sv_gameplayfix_unstickentities.integer)
1168 SV_UnstickEntity(ent);
1170 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1171 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1172 PRVM_G_FLOAT(OFS_RETURN) = 1;
1173 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1174 ent->priv.server->suspendedinairflag = true;
1179 if (trace.fraction != 1)
1181 if (trace.fraction < 1)
1182 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1184 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1185 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1186 PRVM_G_FLOAT(OFS_RETURN) = 1;
1187 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1188 ent->priv.server->suspendedinairflag = true;
1197 void(float style, string value) lightstyle
1200 static void VM_SV_lightstyle(prvm_prog_t *prog)
1207 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1209 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1210 val = PRVM_G_STRING(OFS_PARM1);
1212 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1213 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1216 // change the string in sv
1217 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1219 // send message to all clients on this server
1220 if (sv.state != ss_active)
1223 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1225 if (client->active && client->netconnection)
1227 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1228 MSG_WriteChar (&client->netconnection->message,style);
1229 MSG_WriteString (&client->netconnection->message, val);
1239 static void VM_SV_checkbottom(prvm_prog_t *prog)
1241 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1242 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1250 static void VM_SV_pointcontents(prvm_prog_t *prog)
1252 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1253 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1260 Pick a vector for the player to shoot along
1261 vector aim(entity, missilespeed)
1264 static void VM_SV_aim(prvm_prog_t *prog)
1266 prvm_edict_t *ent, *check, *bestent;
1267 vec3_t start, dir, end, bestdir;
1270 float dist, bestdist;
1273 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1275 // assume failure if it returns early
1276 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1277 // if sv_aim is so high it can't possibly accept anything, skip out early
1278 if (sv_aim.value >= 1)
1281 ent = PRVM_G_EDICT(OFS_PARM0);
1282 if (ent == prog->edicts)
1284 VM_Warning(prog, "aim: can not use world entity\n");
1287 if (ent->priv.server->free)
1289 VM_Warning(prog, "aim: can not use free entity\n");
1292 //speed = PRVM_G_FLOAT(OFS_PARM1);
1294 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1297 // try sending a trace straight
1298 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1299 VectorMA (start, 2048, dir, end);
1300 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1301 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1302 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1304 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1309 // try all possible entities
1310 VectorCopy (dir, bestdir);
1311 bestdist = sv_aim.value;
1314 check = PRVM_NEXT_EDICT(prog->edicts);
1315 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1317 prog->xfunction->builtinsprofile++;
1318 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1322 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1323 continue; // don't aim at teammate
1324 for (j=0 ; j<3 ; j++)
1325 end[j] = PRVM_serveredictvector(check, origin)[j]
1326 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1327 VectorSubtract (end, start, dir);
1328 VectorNormalize (dir);
1329 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1330 if (dist < bestdist)
1331 continue; // to far to turn
1332 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1333 if (tr.ent == check)
1334 { // can shoot at this one
1342 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1343 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1344 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1346 VectorNormalize (end);
1347 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1351 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1356 ===============================================================================
1360 ===============================================================================
1363 #define MSG_BROADCAST 0 // unreliable to all
1364 #define MSG_ONE 1 // reliable to one (msg_entity)
1365 #define MSG_ALL 2 // reliable to all
1366 #define MSG_INIT 3 // write to the init string
1367 #define MSG_ENTITY 5
1369 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1375 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1379 return &sv.datagram;
1382 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1383 entnum = PRVM_NUM_FOR_EDICT(ent);
1384 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1386 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1387 return &sv.reliable_datagram;
1390 return &svs.clients[entnum-1].netconnection->message;
1393 VM_Warning(prog, "WriteDest: bad destination\n");
1395 return &sv.reliable_datagram;
1401 return sv.writeentitiestoclient_msg;
1407 static void VM_SV_WriteByte(prvm_prog_t *prog)
1409 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1410 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1413 static void VM_SV_WriteChar(prvm_prog_t *prog)
1415 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1416 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1419 static void VM_SV_WriteShort(prvm_prog_t *prog)
1421 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1422 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1425 static void VM_SV_WriteLong(prvm_prog_t *prog)
1427 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1428 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1431 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1433 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1434 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1437 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1439 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1440 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1443 static void VM_SV_WriteString(prvm_prog_t *prog)
1445 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1446 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1449 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1451 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1452 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1456 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1458 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1459 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1462 // writes a picture as at most size bytes of data
1464 // IMGNAME \0 SIZE(short) IMGDATA
1465 // if failed to read/compress:
1467 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1468 static void VM_SV_WritePicture(prvm_prog_t *prog)
1470 const char *imgname;
1474 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1476 imgname = PRVM_G_STRING(OFS_PARM1);
1477 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1481 MSG_WriteString(WriteDest(prog), imgname);
1482 if(Image_Compress(imgname, size, &buf, &size))
1485 MSG_WriteShort(WriteDest(prog), size);
1486 SZ_Write(WriteDest(prog), (unsigned char *) buf, size);
1491 MSG_WriteShort(WriteDest(prog), 0);
1495 //////////////////////////////////////////////////////////
1497 static void VM_SV_makestatic(prvm_prog_t *prog)
1502 // allow 0 parameters due to an id1 qc bug in which this function is used
1503 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1504 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1506 if (prog->argc >= 1)
1507 ent = PRVM_G_EDICT(OFS_PARM0);
1509 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1510 if (ent == prog->edicts)
1512 VM_Warning(prog, "makestatic: can not modify world entity\n");
1515 if (ent->priv.server->free)
1517 VM_Warning(prog, "makestatic: can not modify free entity\n");
1522 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1527 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1528 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1529 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1531 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1533 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1534 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1535 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1539 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1540 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1541 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1544 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1545 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1546 for (i=0 ; i<3 ; i++)
1548 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1549 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1552 // throw the entity away now
1553 PRVM_ED_Free(prog, ent);
1556 //=============================================================================
1563 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1569 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1571 ent = PRVM_G_EDICT(OFS_PARM0);
1572 i = PRVM_NUM_FOR_EDICT(ent);
1573 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1575 Con_Print("tried to setspawnparms on a non-client\n");
1579 // copy spawn parms out of the client_t
1580 client = svs.clients + i-1;
1581 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1582 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1589 Returns a color vector indicating the lighting at the requested point.
1591 (Internal Operation note: actually measures the light beneath the point, just like
1592 the model lighting on the client)
1597 static void VM_SV_getlight(prvm_prog_t *prog)
1599 vec3_t ambientcolor, diffusecolor, diffusenormal;
1601 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1602 p = PRVM_G_VECTOR(OFS_PARM0);
1603 VectorClear(ambientcolor);
1604 VectorClear(diffusecolor);
1605 VectorClear(diffusenormal);
1606 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1607 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1608 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1613 unsigned char type; // 1/2/8 or other value if isn't used
1617 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1618 static int vm_customstats_last;
1620 void VM_CustomStats_Clear (void)
1624 Z_Free(vm_customstats);
1625 vm_customstats = NULL;
1626 vm_customstats_last = -1;
1630 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1632 prvm_prog_t *prog = SVVM_prog;
1639 for(i=0; i<vm_customstats_last+1 ;i++)
1641 if(!vm_customstats[i].type)
1643 switch(vm_customstats[i].type)
1645 //string as 16 bytes
1648 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1649 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1650 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1651 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1652 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1654 //float field sent as-is
1656 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1658 //integer value of float field
1660 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1668 // void(float index, float type, .void field) SV_AddStat = #232;
1669 // Set up an auto-sent player stat.
1670 // Client's get thier own fields sent to them. Index may not be less than 32.
1671 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1672 // 1: string (4 stats carrying a total of 16 charactures)
1673 // 2: float (one stat, float converted to an integer for transportation)
1674 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1675 static void VM_SV_AddStat(prvm_prog_t *prog)
1680 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1684 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1687 VM_Warning(prog, "PF_SV_AddStat: not enough memory\n");
1691 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1692 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1693 off = PRVM_G_INT (OFS_PARM2);
1698 VM_Warning(prog, "PF_SV_AddStat: index may not be less than 32\n");
1701 if(i >= (MAX_CL_STATS-32))
1703 VM_Warning(prog, "PF_SV_AddStat: index >= MAX_CL_STATS\n");
1706 if(i > (MAX_CL_STATS-32-4) && type == 1)
1708 VM_Warning(prog, "PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1711 vm_customstats[i].type = type;
1712 vm_customstats[i].fieldoffset = off;
1713 if(vm_customstats_last < i)
1714 vm_customstats_last = i;
1721 copies data from one entity to another
1723 copyentity(src, dst)
1726 static void VM_SV_copyentity(prvm_prog_t *prog)
1728 prvm_edict_t *in, *out;
1729 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1730 in = PRVM_G_EDICT(OFS_PARM0);
1731 if (in == prog->edicts)
1733 VM_Warning(prog, "copyentity: can not read world entity\n");
1736 if (in->priv.server->free)
1738 VM_Warning(prog, "copyentity: can not read free entity\n");
1741 out = PRVM_G_EDICT(OFS_PARM1);
1742 if (out == prog->edicts)
1744 VM_Warning(prog, "copyentity: can not modify world entity\n");
1747 if (out->priv.server->free)
1749 VM_Warning(prog, "copyentity: can not modify free entity\n");
1752 memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
1761 sets the color of a client and broadcasts the update to all connected clients
1763 setcolor(clientent, value)
1766 static void VM_SV_setcolor(prvm_prog_t *prog)
1771 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1772 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1773 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1775 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1777 Con_Print("tried to setcolor a non-client\n");
1781 client = svs.clients + entnum-1;
1784 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1785 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1788 if (client->old_colors != client->colors)
1790 client->old_colors = client->colors;
1791 // send notification to all clients
1792 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1793 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1794 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1802 effect(origin, modelname, startframe, framecount, framerate)
1805 static void VM_SV_effect(prvm_prog_t *prog)
1809 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1810 s = PRVM_G_STRING(OFS_PARM1);
1813 VM_Warning(prog, "effect: no model specified\n");
1817 i = SV_ModelIndex(s, 1);
1820 VM_Warning(prog, "effect: model not precached\n");
1824 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1826 VM_Warning(prog, "effect: framecount < 1\n");
1830 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1832 VM_Warning(prog, "effect: framerate < 1\n");
1836 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1839 static void VM_SV_te_blood(prvm_prog_t *prog)
1841 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1842 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1844 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1845 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1847 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1848 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1849 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1851 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1852 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1853 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1855 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1856 SV_FlushBroadcastMessages();
1859 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1861 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1862 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1864 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1865 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1868 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1869 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1873 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1875 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1877 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1878 SV_FlushBroadcastMessages();
1881 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1883 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1884 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1885 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1887 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1888 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1889 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1891 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1892 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1893 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1894 SV_FlushBroadcastMessages();
1897 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1899 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1900 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1902 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1903 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1911 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1913 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1914 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1915 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1917 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1919 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1920 // gravity true/false
1921 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1923 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1924 SV_FlushBroadcastMessages();
1927 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1929 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1930 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1932 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1933 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1936 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1941 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1943 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1944 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1945 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1947 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1949 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1950 SV_FlushBroadcastMessages();
1953 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1955 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1956 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1958 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1959 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
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_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1970 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1973 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1975 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1976 SV_FlushBroadcastMessages();
1979 static void VM_SV_te_spark(prvm_prog_t *prog)
1981 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1982 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1984 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1985 MSG_WriteByte(&sv.datagram, TE_SPARK);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1989 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1991 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1992 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1993 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1995 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1996 SV_FlushBroadcastMessages();
1999 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2001 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2002 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2003 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2005 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2006 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2007 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2008 SV_FlushBroadcastMessages();
2011 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2013 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2014 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2015 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2017 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2018 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2019 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2020 SV_FlushBroadcastMessages();
2023 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2025 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2026 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2027 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2029 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2030 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2031 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2032 SV_FlushBroadcastMessages();
2035 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2037 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2038 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2039 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2041 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2042 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2043 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2044 SV_FlushBroadcastMessages();
2047 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2049 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2050 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2051 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2054 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2055 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2056 SV_FlushBroadcastMessages();
2059 static void VM_SV_te_customflash(prvm_prog_t *prog)
2061 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2062 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2064 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2065 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2067 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2068 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2069 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2071 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2073 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2075 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2076 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2077 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2078 SV_FlushBroadcastMessages();
2081 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2083 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2084 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2085 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2087 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2088 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2089 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2090 SV_FlushBroadcastMessages();
2093 static void VM_SV_te_spike(prvm_prog_t *prog)
2095 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2096 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2097 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2099 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2100 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2101 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2102 SV_FlushBroadcastMessages();
2105 static void VM_SV_te_superspike(prvm_prog_t *prog)
2107 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2108 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2109 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2111 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2112 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2113 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2114 SV_FlushBroadcastMessages();
2117 static void VM_SV_te_explosion(prvm_prog_t *prog)
2119 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2120 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2121 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2123 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2124 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2125 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2126 SV_FlushBroadcastMessages();
2129 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2131 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2132 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2133 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2135 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2136 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2137 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2138 SV_FlushBroadcastMessages();
2141 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2143 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2144 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2145 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2147 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2148 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2149 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2150 SV_FlushBroadcastMessages();
2153 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2155 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2156 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2157 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2159 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2160 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2161 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2162 SV_FlushBroadcastMessages();
2165 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2167 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2168 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2169 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2171 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2172 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2173 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2174 SV_FlushBroadcastMessages();
2177 static void VM_SV_te_teleport(prvm_prog_t *prog)
2179 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2180 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2181 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2183 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2184 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2185 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2186 SV_FlushBroadcastMessages();
2189 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2191 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2192 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2193 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2195 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2196 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2197 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2199 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2200 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2201 SV_FlushBroadcastMessages();
2204 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2206 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2207 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2208 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2210 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2212 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2213 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2214 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2216 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2217 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2218 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2219 SV_FlushBroadcastMessages();
2222 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2224 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2225 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2226 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2228 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2230 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2231 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2232 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2234 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2235 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2236 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2237 SV_FlushBroadcastMessages();
2240 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2242 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2243 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2244 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2246 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2248 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2249 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2250 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2252 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2253 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2254 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2255 SV_FlushBroadcastMessages();
2258 static void VM_SV_te_beam(prvm_prog_t *prog)
2260 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2261 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2262 MSG_WriteByte(&sv.datagram, TE_BEAM);
2264 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2266 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2267 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2268 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2270 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2271 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2272 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2273 SV_FlushBroadcastMessages();
2276 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2278 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2279 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2280 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2281 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2282 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2283 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2284 SV_FlushBroadcastMessages();
2287 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2289 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2290 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2291 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2293 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2294 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2295 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2297 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2298 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2299 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2301 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2302 SV_FlushBroadcastMessages();
2305 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2306 //this function originally written by KrimZon, made shorter by LordHavoc
2307 static void VM_SV_clientcommand(prvm_prog_t *prog)
2309 client_t *temp_client;
2311 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2313 //find client for this entity
2314 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2315 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2317 Con_Print("PF_clientcommand: entity is not a client\n");
2321 temp_client = host_client;
2322 host_client = svs.clients + i;
2323 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
2324 host_client = temp_client;
2327 //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)
2328 static void VM_SV_setattachment(prvm_prog_t *prog)
2330 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2331 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2332 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2335 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2337 if (e == prog->edicts)
2339 VM_Warning(prog, "setattachment: can not modify world entity\n");
2342 if (e->priv.server->free)
2344 VM_Warning(prog, "setattachment: can not modify free entity\n");
2348 if (tagentity == NULL)
2349 tagentity = prog->edicts;
2353 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2355 model = SV_GetModelFromEdict(tagentity);
2358 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2360 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);
2363 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));
2366 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2367 PRVM_serveredictfloat(e, tag_index) = tagindex;
2370 /////////////////////////////////////////
2371 // DP_MD3_TAGINFO extension coded by VorteX
2373 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2377 i = (int)PRVM_serveredictfloat(e, modelindex);
2378 if (i < 1 || i >= MAX_MODELS)
2381 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2384 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2391 Matrix4x4_CreateIdentity(tag_localmatrix);
2393 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2395 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2406 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2409 float pitchsign = 1;
2411 scale = PRVM_serveredictfloat(ent, scale);
2416 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);
2419 pitchsign = SV_GetPitchSign(prog, ent);
2420 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);
2424 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2427 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2429 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2430 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2431 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2432 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2434 *out = identitymatrix;
2438 // Warnings/errors code:
2439 // 0 - normal (everything all-right)
2442 // 3 - null or non-precached model
2443 // 4 - no tags with requested index
2444 // 5 - runaway loop at attachment chain
2445 extern cvar_t cl_bob;
2446 extern cvar_t cl_bobcycle;
2447 extern cvar_t cl_bobup;
2448 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2451 int modelindex, attachloop;
2452 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2455 *out = identitymatrix; // warnings and errors return identical matrix
2457 if (ent == prog->edicts)
2459 if (ent->priv.server->free)
2462 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2463 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2466 model = SV_GetModelByIndex(modelindex);
2468 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2469 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2470 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2472 tagmatrix = identitymatrix;
2473 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2477 if (attachloop >= 256) // prevent runaway looping
2479 // apply transformation by child's tagindex on parent entity and then
2480 // by parent entity itself
2481 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2482 if (ret && attachloop == 0)
2484 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2485 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2486 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2487 // next iteration we process the parent entity
2488 if (PRVM_serveredictedict(ent, tag_entity))
2490 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2491 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2498 // RENDER_VIEWMODEL magic
2499 if (PRVM_serveredictedict(ent, viewmodelforclient))
2501 Matrix4x4_Copy(&tagmatrix, out);
2502 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2504 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2505 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2508 // Cl_bob, ported from rendering code
2509 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2512 // LordHavoc: this code is *weird*, but not replacable (I think it
2513 // should be done in QC on the server, but oh well, quake is quake)
2514 // LordHavoc: figured out bobup: the time at which the sin is at 180
2515 // degrees (which allows lengthening or squishing the peak or valley)
2516 cycle = sv.time/cl_bobcycle.value;
2517 cycle -= (int)cycle;
2518 if (cycle < cl_bobup.value)
2519 cycle = sin(M_PI * cycle / cl_bobup.value);
2521 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2522 // bob is proportional to velocity in the xy plane
2523 // (don't count Z, or jumping messes it up)
2524 bob = sqrt(PRVM_serveredictvector(ent, velocity)[0]*PRVM_serveredictvector(ent, velocity)[0] + PRVM_serveredictvector(ent, velocity)[1]*PRVM_serveredictvector(ent, velocity)[1])*cl_bob.value;
2525 bob = bob*0.3 + bob*0.7*cycle;
2526 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2533 //float(entity ent, string tagname) gettagindex;
2535 static void VM_SV_gettagindex(prvm_prog_t *prog)
2538 const char *tag_name;
2541 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2543 ent = PRVM_G_EDICT(OFS_PARM0);
2544 tag_name = PRVM_G_STRING(OFS_PARM1);
2546 if (ent == prog->edicts)
2548 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2551 if (ent->priv.server->free)
2553 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2558 if (!SV_GetModelFromEdict(ent))
2559 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2562 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2564 if(developer_extra.integer)
2565 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2567 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2570 //vector(entity ent, float tagindex) gettaginfo;
2571 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2575 matrix4x4_t tag_matrix;
2576 matrix4x4_t tag_localmatrix;
2578 const char *tagname;
2580 vec3_t fo, le, up, trans;
2581 const dp_model_t *model;
2583 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2585 e = PRVM_G_EDICT(OFS_PARM0);
2586 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2588 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2589 Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
2590 VectorScale(le, -1, PRVM_serverglobalvector(v_right));
2591 model = SV_GetModelFromEdict(e);
2592 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2593 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
2594 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2595 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2596 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2598 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2599 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2600 VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
2601 VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
2602 VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
2603 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2608 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2611 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2614 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2617 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2620 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2625 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2626 static void VM_SV_dropclient(prvm_prog_t *prog)
2629 client_t *oldhostclient;
2630 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2631 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2632 if (clientnum < 0 || clientnum >= svs.maxclients)
2634 VM_Warning(prog, "dropclient: not a client\n");
2637 if (!svs.clients[clientnum].active)
2639 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2642 oldhostclient = host_client;
2643 host_client = svs.clients + clientnum;
2644 SV_DropClient(false);
2645 host_client = oldhostclient;
2648 //entity() spawnclient (DP_SV_BOTCLIENT)
2649 static void VM_SV_spawnclient(prvm_prog_t *prog)
2653 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2654 prog->xfunction->builtinsprofile += 2;
2656 for (i = 0;i < svs.maxclients;i++)
2658 if (!svs.clients[i].active)
2660 prog->xfunction->builtinsprofile += 100;
2661 SV_ConnectClient (i, NULL);
2662 // this has to be set or else ClientDisconnect won't be called
2663 // we assume the qc will call ClientConnect...
2664 svs.clients[i].clientconnectcalled = true;
2665 ed = PRVM_EDICT_NUM(i + 1);
2669 VM_RETURN_EDICT(ed);
2672 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2673 static void VM_SV_clienttype(prvm_prog_t *prog)
2676 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2677 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2678 if (clientnum < 0 || clientnum >= svs.maxclients)
2679 PRVM_G_FLOAT(OFS_RETURN) = 3;
2680 else if (!svs.clients[clientnum].active)
2681 PRVM_G_FLOAT(OFS_RETURN) = 0;
2682 else if (svs.clients[clientnum].netconnection)
2683 PRVM_G_FLOAT(OFS_RETURN) = 1;
2685 PRVM_G_FLOAT(OFS_RETURN) = 2;
2692 string(string key) serverkey
2695 static void VM_SV_serverkey(prvm_prog_t *prog)
2697 char string[VM_STRINGTEMP_LENGTH];
2698 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2699 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2700 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2703 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2704 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2709 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2711 e = PRVM_G_EDICT(OFS_PARM0);
2712 if (e == prog->edicts)
2714 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2717 if (e->priv.server->free)
2719 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2722 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2723 if (i <= 0 || i >= MAX_MODELS)
2725 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2728 if (!sv.model_precache[i][0])
2730 VM_Warning(prog, "setmodelindex: model not precached\n");
2734 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2735 PRVM_serveredictfloat(e, modelindex) = i;
2737 mod = SV_GetModelByIndex(i);
2741 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2742 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2744 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2747 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2750 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2751 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2754 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2756 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2758 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2759 if (i <= 0 || i >= MAX_MODELS)
2761 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2764 if (!sv.model_precache[i][0])
2766 VM_Warning(prog, "modelnameforindex: model not precached\n");
2770 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2773 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2774 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2777 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2778 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2781 PRVM_G_FLOAT(OFS_RETURN) = i;
2784 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2785 static void VM_SV_trailparticles(prvm_prog_t *prog)
2787 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2789 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2792 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2793 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2794 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2795 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2796 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2797 SV_FlushBroadcastMessages();
2800 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2801 static void VM_SV_pointparticles(prvm_prog_t *prog)
2803 int effectnum, count;
2805 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2807 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2810 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2811 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2812 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2813 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2814 if (count == 1 && !VectorLength2(vel))
2817 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2818 MSG_WriteShort(&sv.datagram, effectnum);
2819 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2823 // 1+2+12+12+2=29 bytes
2824 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2825 MSG_WriteShort(&sv.datagram, effectnum);
2826 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2827 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2828 MSG_WriteShort(&sv.datagram, count);
2831 SV_FlushBroadcastMessages();
2834 //PF_setpause, // void(float pause) setpause = #531;
2835 static void VM_SV_setpause(prvm_prog_t *prog) {
2837 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2838 if (pauseValue != 0) { //pause the game
2840 sv.pausedstart = realtime;
2841 } else { //disable pause, in case it was enabled
2842 if (sv.paused != 0) {
2847 // send notification to all clients
2848 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2849 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2852 // #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.
2853 static void VM_SV_skel_create(prvm_prog_t *prog)
2855 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2856 dp_model_t *model = SV_GetModelByIndex(modelindex);
2857 skeleton_t *skeleton;
2859 PRVM_G_FLOAT(OFS_RETURN) = 0;
2860 if (!model || !model->num_bones)
2862 for (i = 0;i < MAX_EDICTS;i++)
2863 if (!prog->skeletons[i])
2865 if (i == MAX_EDICTS)
2867 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2868 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2869 skeleton->model = model;
2870 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2871 // initialize to identity matrices
2872 for (i = 0;i < skeleton->model->num_bones;i++)
2873 skeleton->relativetransforms[i] = identitymatrix;
2876 // #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
2877 static void VM_SV_skel_build(prvm_prog_t *prog)
2879 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2880 skeleton_t *skeleton;
2881 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2882 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2883 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2884 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2885 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2886 dp_model_t *model = SV_GetModelByIndex(modelindex);
2891 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2892 frameblend_t frameblend[MAX_FRAMEBLENDS];
2893 matrix4x4_t blendedmatrix;
2895 PRVM_G_FLOAT(OFS_RETURN) = 0;
2896 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2898 firstbone = max(0, firstbone);
2899 lastbone = min(lastbone, model->num_bones - 1);
2900 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2901 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2902 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
2903 blendfrac = 1.0f - retainfrac;
2904 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2905 frameblend[numblends].lerp *= blendfrac;
2906 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2908 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2909 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2910 for (blendindex = 0;blendindex < numblends;blendindex++)
2912 Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2913 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2915 skeleton->relativetransforms[bonenum] = blendedmatrix;
2917 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2920 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2921 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
2923 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2924 skeleton_t *skeleton;
2925 PRVM_G_FLOAT(OFS_RETURN) = 0;
2926 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2928 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2931 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2932 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
2934 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2935 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2936 skeleton_t *skeleton;
2937 PRVM_G_INT(OFS_RETURN) = 0;
2938 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2940 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2942 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
2945 // #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)
2946 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
2948 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2949 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2950 skeleton_t *skeleton;
2951 PRVM_G_FLOAT(OFS_RETURN) = 0;
2952 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2954 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2956 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2959 // #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
2960 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
2962 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2963 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2964 skeleton_t *skeleton;
2965 PRVM_G_FLOAT(OFS_RETURN) = 0;
2966 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2968 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2971 // #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)
2972 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
2974 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2975 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2976 skeleton_t *skeleton;
2978 vec3_t forward, left, up, origin;
2979 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2980 VectorClear(PRVM_clientglobalvector(v_forward));
2981 VectorClear(PRVM_clientglobalvector(v_right));
2982 VectorClear(PRVM_clientglobalvector(v_up));
2983 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2985 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2987 matrix = skeleton->relativetransforms[bonenum];
2988 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2989 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2990 VectorNegate(left, PRVM_clientglobalvector(v_right));
2991 VectorCopy(up, PRVM_clientglobalvector(v_up));
2992 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2995 // #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)
2996 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
2998 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2999 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3000 skeleton_t *skeleton;
3003 vec3_t forward, left, up, origin;
3004 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3005 VectorClear(PRVM_clientglobalvector(v_forward));
3006 VectorClear(PRVM_clientglobalvector(v_right));
3007 VectorClear(PRVM_clientglobalvector(v_up));
3008 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3010 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3012 matrix = skeleton->relativetransforms[bonenum];
3013 // convert to absolute
3014 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3017 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3019 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3020 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3021 VectorNegate(left, PRVM_clientglobalvector(v_right));
3022 VectorCopy(up, PRVM_clientglobalvector(v_up));
3023 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3026 // #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)
3027 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3029 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3030 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3031 vec3_t forward, left, up, origin;
3032 skeleton_t *skeleton;
3034 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3036 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3038 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3039 VectorNegate(PRVM_clientglobalvector(v_right), left);
3040 VectorCopy(PRVM_clientglobalvector(v_up), up);
3041 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3042 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3043 skeleton->relativetransforms[bonenum] = matrix;
3046 // #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)
3047 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3049 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3050 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3051 vec3_t forward, left, up, origin;
3052 skeleton_t *skeleton;
3055 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3057 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3059 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3060 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3061 VectorNegate(PRVM_clientglobalvector(v_right), left);
3062 VectorCopy(PRVM_clientglobalvector(v_up), up);
3063 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3064 temp = skeleton->relativetransforms[bonenum];
3065 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3068 // #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)
3069 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3071 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3072 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3073 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3075 vec3_t forward, left, up, origin;
3076 skeleton_t *skeleton;
3079 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3081 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3082 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3083 VectorNegate(PRVM_clientglobalvector(v_right), left);
3084 VectorCopy(PRVM_clientglobalvector(v_up), up);
3085 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3086 firstbone = max(0, firstbone);
3087 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3088 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3090 temp = skeleton->relativetransforms[bonenum];
3091 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3095 // #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
3096 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3098 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3099 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3100 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3101 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3103 skeleton_t *skeletondst;
3104 skeleton_t *skeletonsrc;
3105 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3107 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3109 firstbone = max(0, firstbone);
3110 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3111 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3112 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3113 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3116 // #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)
3117 static void VM_SV_skel_delete(prvm_prog_t *prog)
3119 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3120 skeleton_t *skeleton;
3121 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3124 prog->skeletons[skeletonindex] = NULL;
3127 // #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
3128 static void VM_SV_frameforname(prvm_prog_t *prog)
3130 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3131 dp_model_t *model = SV_GetModelByIndex(modelindex);
3132 const char *name = PRVM_G_STRING(OFS_PARM1);
3134 PRVM_G_FLOAT(OFS_RETURN) = -1;
3135 if (!model || !model->animscenes)
3137 for (i = 0;i < model->numframes;i++)
3139 if (!strcasecmp(model->animscenes[i].name, name))
3141 PRVM_G_FLOAT(OFS_RETURN) = i;
3147 // #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.
3148 static void VM_SV_frameduration(prvm_prog_t *prog)
3150 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3151 dp_model_t *model = SV_GetModelByIndex(modelindex);
3152 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3153 PRVM_G_FLOAT(OFS_RETURN) = 0;
3154 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3156 if (model->animscenes[framenum].framerate)
3157 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3161 prvm_builtin_t vm_sv_builtins[] = {
3162 NULL, // #0 NULL function (not callable) (QUAKE)
3163 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3164 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3165 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3166 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3167 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3168 VM_break, // #6 void() break (QUAKE)
3169 VM_random, // #7 float() random (QUAKE)
3170 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3171 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3172 VM_error, // #10 void(string e) error (QUAKE)
3173 VM_objerror, // #11 void(string e) objerror (QUAKE)
3174 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3175 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3176 VM_spawn, // #14 entity() spawn (QUAKE)
3177 VM_remove, // #15 void(entity e) remove (QUAKE)
3178 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3179 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3180 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3181 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3182 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3183 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3184 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3185 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3186 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3187 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3188 VM_ftos, // #26 string(float f) ftos (QUAKE)
3189 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3190 VM_coredump, // #28 void() coredump (QUAKE)
3191 VM_traceon, // #29 void() traceon (QUAKE)
3192 VM_traceoff, // #30 void() traceoff (QUAKE)
3193 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3194 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3195 NULL, // #33 (QUAKE)
3196 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3197 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3198 VM_rint, // #36 float(float v) rint (QUAKE)
3199 VM_floor, // #37 float(float v) floor (QUAKE)
3200 VM_ceil, // #38 float(float v) ceil (QUAKE)
3201 NULL, // #39 (QUAKE)
3202 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3203 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3204 NULL, // #42 (QUAKE)
3205 VM_fabs, // #43 float(float f) fabs (QUAKE)
3206 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3207 VM_cvar, // #45 float(string s) cvar (QUAKE)
3208 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3209 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3210 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3211 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3212 NULL, // #50 (QUAKE)
3213 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3214 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3215 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3216 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3217 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3218 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3219 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3220 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3221 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3222 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3223 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3224 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3225 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3226 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3227 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3228 NULL, // #66 (QUAKE)
3229 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3230 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3231 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3232 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3233 NULL, // #71 (QUAKE)
3234 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3235 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3236 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3237 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3238 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3239 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3240 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3241 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3242 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3243 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3244 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3245 NULL, // #83 (QUAKE)
3246 NULL, // #84 (QUAKE)
3247 NULL, // #85 (QUAKE)
3248 NULL, // #86 (QUAKE)
3249 NULL, // #87 (QUAKE)
3250 NULL, // #88 (QUAKE)
3251 NULL, // #89 (QUAKE)
3252 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3253 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3254 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3255 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3256 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3257 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3258 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3259 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3260 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3261 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3262 // FrikaC and Telejano range #100-#199
3273 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3274 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3275 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3276 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3277 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3278 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3279 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3280 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3281 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3282 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3363 // FTEQW range #200-#299
3382 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3385 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3386 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3387 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3388 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3389 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3390 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3391 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3392 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3393 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3394 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3396 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3404 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3427 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.
3428 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
3429 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3430 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3431 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)
3432 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
3433 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)
3434 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)
3435 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)
3436 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)
3437 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)
3438 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
3439 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)
3440 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
3441 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.
3464 // CSQC range #300-#399
3465 NULL, // #300 void() clearscene (EXT_CSQC)
3466 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3467 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3468 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3469 NULL, // #304 void() renderscene (EXT_CSQC)
3470 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3471 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3472 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3473 NULL, // #308 void() R_EndPolygon
3475 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3476 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3480 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3481 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3482 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3483 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3484 NULL, // #319 void(string name) freepic (EXT_CSQC)
3485 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3486 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3487 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3488 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3489 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3490 NULL, // #325 void(void) drawresetcliparea
3495 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3496 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3497 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3498 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3499 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3500 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3501 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3502 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3503 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3504 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3505 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3506 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3507 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3508 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3509 NULL, // #344 vector() getmousepos (EXT_CSQC)
3510 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3511 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3512 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3513 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3514 NULL, // #349 float() isdemo (EXT_CSQC)
3515 VM_isserver, // #350 float() isserver (EXT_CSQC)
3516 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3517 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3518 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3519 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3525 NULL, // #360 float() readbyte (EXT_CSQC)
3526 NULL, // #361 float() readchar (EXT_CSQC)
3527 NULL, // #362 float() readshort (EXT_CSQC)
3528 NULL, // #363 float() readlong (EXT_CSQC)
3529 NULL, // #364 float() readcoord (EXT_CSQC)
3530 NULL, // #365 float() readangle (EXT_CSQC)
3531 NULL, // #366 string() readstring (EXT_CSQC)
3532 NULL, // #367 float() readfloat (EXT_CSQC)
3565 // LordHavoc's range #400-#499
3566 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3567 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3568 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3569 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3570 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3571 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3572 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3573 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3574 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)
3575 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3576 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3577 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3578 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3579 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3580 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3581 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3582 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3583 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3584 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3585 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3586 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3587 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3588 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3589 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3590 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3591 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3592 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3593 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3594 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3595 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3596 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3597 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3598 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3599 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3600 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3601 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3602 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3603 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3604 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3605 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3606 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3607 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3608 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3609 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3610 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3611 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3612 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3613 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3614 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3615 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3616 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3617 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3618 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3619 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3620 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3621 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3622 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3623 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3625 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3626 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3627 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3628 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3629 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3630 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3631 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3632 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3633 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3634 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3635 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3637 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3638 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3639 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3640 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3641 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3642 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3643 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3644 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3645 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3646 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3647 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3648 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3649 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3650 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3651 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3652 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3660 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3661 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3662 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3663 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3664 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3665 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3666 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3667 VM_SV_WritePicture, // #501
3669 VM_whichpack, // #503 string(string) whichpack = #503;
3676 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3677 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3678 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3679 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)
3680 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3681 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3682 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3683 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3684 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3685 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3695 VM_loadfromdata, // #529
3696 VM_loadfromfile, // #530
3697 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3699 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3700 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3706 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3707 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3708 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3771 VM_callfunction, // #605
3772 VM_writetofile, // #606
3773 VM_isfunction, // #607
3779 VM_parseentitydata, // #613
3790 VM_SV_getextresponse, // #624 string getextresponse(void)
3793 VM_sprintf, // #627 string sprintf(string format, ...)
3794 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3795 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3805 VM_digest_hex, // #639
3809 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3811 void SVVM_init_cmd(prvm_prog_t *prog)
3816 void SVVM_reset_cmd(prvm_prog_t *prog)
3818 World_End(&sv.world);
3819 if(PRVM_serverfunction(SV_Shutdown))
3821 func_t s = PRVM_serverfunction(SV_Shutdown);
3822 PRVM_serverglobalfloat(time) = sv.time;
3823 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3824 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");