6 //============================================================================
11 const char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
24 "DP_CSQC_ENTITYWORLDOBJECT "
25 "DP_CSQC_ENTITYMODELLIGHT "
26 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
27 "DP_CSQC_MULTIFRAME_INTERPOLATION "
28 "DP_CSQC_BOXPARTICLES "
29 "DP_CSQC_SPAWNPARTICLE "
30 "DP_CSQC_QUERYRENDERENTITY "
31 "DP_CSQC_ROTATEMOVES "
44 "DP_EF_RESTARTANIM_BIT "
49 "DP_ENT_CUSTOMCOLORMAP "
50 "DP_ENT_EXTERIORMODELTOCLIENT "
53 "DP_ENT_LOWPRECISION "
55 "DP_ENT_TRAILEFFECTNUM "
58 "DP_GFX_EXTERNALTEXTURES "
59 "DP_GFX_EXTERNALTEXTURES_PERMAP "
61 "DP_GFX_MODEL_INTERPOLATION "
62 "DP_GFX_QUAKE3MODELTAGS "
66 "DP_GFX_FONTS_FREETYPE "
68 "DP_FONT_VARIABLEWIDTH "
70 "DP_HALFLIFE_MAP_CVAR "
73 "DP_LIGHTSTYLE_STATICVALUE "
77 "DP_MOVETYPEBOUNCEMISSILE "
78 "DP_MOVETYPEFLYWORLDONLY "
81 "DP_QC_ASINACOSATANATAN2TAN "
87 "DP_QC_CVAR_DEFSTRING "
88 "DP_QC_CVAR_DESCRIPTION "
95 "DP_QC_EXTRESPONSEPACKET "
97 "DP_QC_FINDCHAINFLAGS "
98 "DP_QC_FINDCHAINFLOAT "
99 "DP_QC_FINDCHAIN_TOFIELD "
105 "DP_QC_GETSURFACETRIANGLE "
106 "DP_QC_GETSURFACEPOINTATTRIBUTE "
108 "DP_QC_GETTAGINFO_BONEPROPERTIES "
110 "DP_QC_GETTIME_CDTRACK "
113 "DP_QC_MULTIPLETEMPSTRINGS "
114 "DP_QC_NUM_FOR_EDICT "
116 "DP_QC_SINCOSSQRTPOW "
119 "DP_QC_STRINGBUFFERS "
120 "DP_QC_STRINGBUFFERS_CVARLIST "
121 "DP_QC_STRINGCOLORFUNCTIONS "
122 "DP_QC_STRING_CASE_FUNCTIONS "
124 "DP_QC_TOKENIZEBYSEPARATOR "
125 "DP_QC_TOKENIZE_CONSOLE "
128 "DP_QC_TRACE_MOVETYPE_HITMODEL "
129 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
130 "DP_QC_UNLIMITEDTEMPSTRINGS "
134 "DP_QC_VECTOANGLES_WITH_ROLL "
135 "DP_QC_VECTORVECTORS "
142 "DP_SKELETONOBJECTS "
143 "DP_SND_DIRECTIONLESSATTNNONE "
145 "DP_SND_SOUND7_WIP1 "
149 "DP_SND_GETSOUNDTIME "
151 "DP_VIDEO_SUBTITLES "
155 "DP_SV_BOUNCEFACTOR "
156 "DP_SV_CLIENTCAMERA "
157 "DP_SV_CLIENTCOLORS "
160 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
161 "DP_SV_DISCARDABLEDEMO "
162 "DP_SV_DRAWONLYTOCLIENT "
165 "DP_SV_ENTITYCONTENTSTRANSITION "
166 "DP_SV_MODELFLAGS_AS_EFFECTS "
167 "DP_SV_MOVETYPESTEP_LANDEVENT "
169 "DP_SV_NODRAWTOCLIENT "
170 "DP_SV_ONENTITYNOSPAWNFUNCTION "
171 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
173 "DP_SV_PING_PACKETLOSS "
174 "DP_SV_PLAYERPHYSICS "
176 "DP_SV_POINTPARTICLES "
178 "DP_SV_PRECACHEANYTIME "
182 "DP_SV_ROTATINGBMODEL "
186 "DP_SV_SPAWNFUNC_PREFIX "
187 "DP_SV_WRITEPICTURE "
188 "DP_SV_WRITEUNTERMINATEDSTRING "
192 "DP_TE_EXPLOSIONRGB "
194 "DP_TE_PARTICLECUBE "
195 "DP_TE_PARTICLERAIN "
196 "DP_TE_PARTICLESNOW "
198 "DP_TE_QUADEFFECTS1 "
201 "DP_TE_STANDARDEFFECTBUILTINS "
202 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
206 "FTE_CSQC_SKELETONOBJECTS "
209 "KRIMZON_SV_PARSECLIENTCOMMAND "
212 "NEXUIZ_PLAYERMODEL "
214 "PRYDON_CLIENTCURSOR "
215 "TENEBRAE_GFX_DLIGHTS "
218 //"EXT_CSQC " // not ready yet
225 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.
227 setorigin (entity, origin)
230 static void VM_SV_setorigin (void)
235 VM_SAFEPARMCOUNT(2, VM_setorigin);
237 e = PRVM_G_EDICT(OFS_PARM0);
238 if (e == prog->edicts)
240 VM_Warning("setorigin: can not modify world entity\n");
243 if (e->priv.server->free)
245 VM_Warning("setorigin: can not modify free entity\n");
248 org = PRVM_G_VECTOR(OFS_PARM1);
249 VectorCopy (org, PRVM_serveredictvector(e, origin));
253 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
254 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
258 for (i=0 ; i<3 ; i++)
260 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
262 // set derived values
263 VectorCopy (min, PRVM_serveredictvector(e, mins));
264 VectorCopy (max, PRVM_serveredictvector(e, maxs));
265 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
274 the size box is rotated by the current angle
275 LordHavoc: no it isn't...
277 setsize (entity, minvector, maxvector)
280 static void VM_SV_setsize (void)
285 VM_SAFEPARMCOUNT(3, VM_setsize);
287 e = PRVM_G_EDICT(OFS_PARM0);
288 if (e == prog->edicts)
290 VM_Warning("setsize: can not modify world entity\n");
293 if (e->priv.server->free)
295 VM_Warning("setsize: can not modify free entity\n");
298 min = PRVM_G_VECTOR(OFS_PARM1);
299 max = PRVM_G_VECTOR(OFS_PARM2);
300 SetMinMaxSize (e, min, max, false);
308 setmodel(entity, model)
311 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
312 static void VM_SV_setmodel (void)
318 VM_SAFEPARMCOUNT(2, VM_setmodel);
320 e = PRVM_G_EDICT(OFS_PARM0);
321 if (e == prog->edicts)
323 VM_Warning("setmodel: can not modify world entity\n");
326 if (e->priv.server->free)
328 VM_Warning("setmodel: can not modify free entity\n");
331 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
332 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
333 PRVM_serveredictfloat(e, modelindex) = i;
335 mod = SV_GetModelByIndex(i);
339 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
340 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
342 SetMinMaxSize (e, quakemins, quakemaxs, true);
345 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
352 single print to a specific client
354 sprint(clientent, value)
357 static void VM_SV_sprint (void)
361 char string[VM_STRINGTEMP_LENGTH];
363 VM_VarString(1, string, sizeof(string));
365 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
367 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
368 // LordHavoc: div0 requested that sprintto world operate like print
375 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
377 VM_Warning("tried to centerprint to a non-client\n");
381 client = svs.clients + entnum-1;
382 if (!client->netconnection)
385 MSG_WriteChar(&client->netconnection->message,svc_print);
386 MSG_WriteString(&client->netconnection->message, string);
394 single print to a specific client
396 centerprint(clientent, value)
399 static void VM_SV_centerprint (void)
403 char string[VM_STRINGTEMP_LENGTH];
405 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
407 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
409 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
411 VM_Warning("tried to centerprint to a non-client\n");
415 client = svs.clients + entnum-1;
416 if (!client->netconnection)
419 VM_VarString(1, string, sizeof(string));
420 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
421 MSG_WriteString(&client->netconnection->message, string);
428 particle(origin, color, count)
431 static void VM_SV_particle (void)
437 VM_SAFEPARMCOUNT(4, VM_SV_particle);
439 org = PRVM_G_VECTOR(OFS_PARM0);
440 dir = PRVM_G_VECTOR(OFS_PARM1);
441 color = PRVM_G_FLOAT(OFS_PARM2);
442 count = PRVM_G_FLOAT(OFS_PARM3);
443 SV_StartParticle (org, dir, (int)color, (int)count);
453 static void VM_SV_ambientsound (void)
457 float vol, attenuation;
460 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
462 pos = PRVM_G_VECTOR (OFS_PARM0);
463 samp = PRVM_G_STRING(OFS_PARM1);
464 vol = PRVM_G_FLOAT(OFS_PARM2);
465 attenuation = PRVM_G_FLOAT(OFS_PARM3);
467 // check to see if samp was properly precached
468 soundnum = SV_SoundIndex(samp, 1);
476 // add an svc_spawnambient command to the level signon packet
479 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
481 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
483 MSG_WriteVector(&sv.signon, pos, sv.protocol);
485 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
486 MSG_WriteShort (&sv.signon, soundnum);
488 MSG_WriteByte (&sv.signon, soundnum);
490 MSG_WriteByte (&sv.signon, (int)(vol*255));
491 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
499 Each entity can have eight independant sound sources, like voice,
502 Channel 0 is an auto-allocate channel, the others override anything
503 already running on that entity/channel pair.
505 An attenuation of 0 will play full volume everywhere in the level.
506 Larger attenuations will drop off.
510 static void VM_SV_sound (void)
514 prvm_edict_t *entity;
520 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
522 entity = PRVM_G_EDICT(OFS_PARM0);
523 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
524 sample = PRVM_G_STRING(OFS_PARM2);
525 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
528 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
532 attenuation = PRVM_G_FLOAT(OFS_PARM4);
536 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
541 if(channel >= 8 && channel <= 15) // weird QW feature
543 flags |= CHANFLAG_RELIABLE;
548 flags = PRVM_G_FLOAT(OFS_PARM6);
550 if (volume < 0 || volume > 255)
552 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
556 if (attenuation < 0 || attenuation > 4)
558 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
562 channel = CHAN_USER2ENGINE(channel);
564 if (!IS_CHAN(channel))
566 VM_Warning("SV_StartSound: channel must be in range 0-127\n");
570 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE, pitchchange);
577 Follows the same logic as VM_SV_sound, except instead of
578 an entity, an origin for the sound is provided, and channel
579 is omitted (since no entity is being tracked).
583 static void VM_SV_pointsound(void)
591 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
593 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
594 sample = PRVM_G_STRING(OFS_PARM1);
595 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
596 attenuation = PRVM_G_FLOAT(OFS_PARM3);
597 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
599 if (volume < 0 || volume > 255)
601 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
605 if (attenuation < 0 || attenuation > 4)
607 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
611 SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
618 Used for use tracing and shot targeting
619 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
620 if the tryents flag is set.
622 traceline (vector1, vector2, movetype, ignore)
625 static void VM_SV_traceline (void)
632 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
634 prog->xfunction->builtinsprofile += 30;
636 v1 = PRVM_G_VECTOR(OFS_PARM0);
637 v2 = PRVM_G_VECTOR(OFS_PARM1);
638 move = (int)PRVM_G_FLOAT(OFS_PARM2);
639 ent = PRVM_G_EDICT(OFS_PARM3);
641 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]))
642 PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
644 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
646 VM_SetTraceGlobals(&trace);
654 Used for use tracing and shot targeting
655 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
656 if the tryents flag is set.
658 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
661 // LordHavoc: added this for my own use, VERY useful, similar to traceline
662 static void VM_SV_tracebox (void)
664 float *v1, *v2, *m1, *m2;
669 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
671 prog->xfunction->builtinsprofile += 30;
673 v1 = PRVM_G_VECTOR(OFS_PARM0);
674 m1 = PRVM_G_VECTOR(OFS_PARM1);
675 m2 = PRVM_G_VECTOR(OFS_PARM2);
676 v2 = PRVM_G_VECTOR(OFS_PARM3);
677 move = (int)PRVM_G_FLOAT(OFS_PARM4);
678 ent = PRVM_G_EDICT(OFS_PARM5);
680 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]))
681 PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
683 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
685 VM_SetTraceGlobals(&trace);
688 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
693 vec3_t original_origin;
694 vec3_t original_velocity;
695 vec3_t original_angles;
696 vec3_t original_avelocity;
699 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
700 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
701 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
702 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
704 gravity = PRVM_serveredictfloat(tossent, gravity);
707 gravity *= sv_gravity.value * 0.025;
709 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
711 SV_CheckVelocity (tossent);
712 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
713 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
714 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
715 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
716 trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
717 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
718 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
720 if (trace.fraction < 1)
724 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
725 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
726 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
727 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
732 static void VM_SV_tracetoss (void)
736 prvm_edict_t *ignore;
738 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
740 prog->xfunction->builtinsprofile += 600;
742 ent = PRVM_G_EDICT(OFS_PARM0);
743 if (ent == prog->edicts)
745 VM_Warning("tracetoss: can not use world entity\n");
748 ignore = PRVM_G_EDICT(OFS_PARM1);
750 trace = SV_Trace_Toss (ent, ignore);
752 VM_SetTraceGlobals(&trace);
755 //============================================================================
757 static int checkpvsbytes;
758 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
760 static int VM_SV_newcheckclient (int check)
766 // cycle to the next one
768 check = bound(1, check, svs.maxclients);
769 if (check == svs.maxclients)
777 prog->xfunction->builtinsprofile++;
779 if (i == svs.maxclients+1)
781 // look up the client's edict
782 ent = PRVM_EDICT_NUM(i);
783 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
784 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
786 // found a valid client (possibly the same one again)
790 // get the PVS for the entity
791 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
793 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
794 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
803 Returns a client (or object that has a client enemy) that would be a
806 If there is more than one valid option, they are cycled each frame
808 If (self.origin + self.viewofs) is not in the PVS of the current target,
809 it is not returned at all.
814 int c_invis, c_notvis;
815 static void VM_SV_checkclient (void)
817 prvm_edict_t *ent, *self;
820 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
822 // find a new check if on a new frame
823 if (sv.time - sv.lastchecktime >= 0.1)
825 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
826 sv.lastchecktime = sv.time;
829 // return check if it might be visible
830 ent = PRVM_EDICT_NUM(sv.lastcheck);
831 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
833 VM_RETURN_EDICT(prog->edicts);
837 // if current entity can't possibly see the check entity, return 0
838 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
839 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
840 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
843 VM_RETURN_EDICT(prog->edicts);
847 // might be able to see it
849 VM_RETURN_EDICT(ent);
852 //============================================================================
858 Checks if an entity is in a point's PVS.
859 Should be fast but can be inexact.
861 float checkpvs(vector viewpos, entity viewee) = #240;
864 static void VM_SV_checkpvs (void)
867 prvm_edict_t *viewee;
872 unsigned char fatpvs[MAX_MAP_LEAFS/8];
875 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
876 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
877 viewee = PRVM_G_EDICT(OFS_PARM1);
879 if(viewee->priv.server->free)
881 VM_Warning("checkpvs: can not check free entity\n");
882 PRVM_G_FLOAT(OFS_RETURN) = 4;
887 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
889 // no PVS support on this worldmodel... darn
890 PRVM_G_FLOAT(OFS_RETURN) = 3;
893 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
896 // viewpos isn't in any PVS... darn
897 PRVM_G_FLOAT(OFS_RETURN) = 2;
900 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
902 // using fat PVS like FTEQW does (slow)
903 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
905 // no PVS support on this worldmodel... darn
906 PRVM_G_FLOAT(OFS_RETURN) = 3;
909 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
912 // viewpos isn't in any PVS... darn
913 PRVM_G_FLOAT(OFS_RETURN) = 2;
916 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
925 Sends text over to the client's execution buffer
927 stuffcmd (clientent, value, ...)
930 static void VM_SV_stuffcmd (void)
934 char string[VM_STRINGTEMP_LENGTH];
936 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
938 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
939 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
941 VM_Warning("Can't stuffcmd to a non-client\n");
945 VM_VarString(1, string, sizeof(string));
948 host_client = svs.clients + entnum-1;
949 Host_ClientCommands ("%s", string);
957 Returns a chain of entities that have origins within a spherical area
959 findradius (origin, radius)
962 static void VM_SV_findradius (void)
964 prvm_edict_t *ent, *chain;
965 vec_t radius, radius2;
966 vec3_t org, eorg, mins, maxs;
969 static prvm_edict_t *touchedicts[MAX_EDICTS];
972 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
975 chainfield = PRVM_G_INT(OFS_PARM2);
977 chainfield = prog->fieldoffsets.chain;
979 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
981 chain = (prvm_edict_t *)prog->edicts;
983 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
984 radius = PRVM_G_FLOAT(OFS_PARM1);
985 radius2 = radius * radius;
987 mins[0] = org[0] - (radius + 1);
988 mins[1] = org[1] - (radius + 1);
989 mins[2] = org[2] - (radius + 1);
990 maxs[0] = org[0] + (radius + 1);
991 maxs[1] = org[1] + (radius + 1);
992 maxs[2] = org[2] + (radius + 1);
993 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
994 if (numtouchedicts > MAX_EDICTS)
996 // this never happens
997 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
998 numtouchedicts = MAX_EDICTS;
1000 for (i = 0;i < numtouchedicts;i++)
1002 ent = touchedicts[i];
1003 prog->xfunction->builtinsprofile++;
1004 // Quake did not return non-solid entities but darkplaces does
1005 // (note: this is the reason you can't blow up fallen zombies)
1006 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1008 // LordHavoc: compare against bounding box rather than center so it
1009 // doesn't miss large objects, and use DotProduct instead of Length
1010 // for a major speedup
1011 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1012 if (sv_gameplayfix_findradiusdistancetobox.integer)
1014 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1015 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1016 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1019 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1020 if (DotProduct(eorg, eorg) < radius2)
1022 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1027 VM_RETURN_EDICT(chain);
1030 static void VM_SV_precache_sound (void)
1032 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1033 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1036 static void VM_SV_precache_model (void)
1038 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1039 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1040 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1047 float(float yaw, float dist[, settrace]) walkmove
1050 static void VM_SV_walkmove (void)
1059 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1061 // assume failure if it returns early
1062 PRVM_G_FLOAT(OFS_RETURN) = 0;
1064 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1065 if (ent == prog->edicts)
1067 VM_Warning("walkmove: can not modify world entity\n");
1070 if (ent->priv.server->free)
1072 VM_Warning("walkmove: can not modify free entity\n");
1075 yaw = PRVM_G_FLOAT(OFS_PARM0);
1076 dist = PRVM_G_FLOAT(OFS_PARM1);
1077 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1079 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1082 yaw = yaw*M_PI*2 / 360;
1084 move[0] = cos(yaw)*dist;
1085 move[1] = sin(yaw)*dist;
1088 // save program state, because SV_movestep may call other progs
1089 oldf = prog->xfunction;
1090 oldself = PRVM_serverglobaledict(self);
1092 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1095 // restore program state
1096 prog->xfunction = oldf;
1097 PRVM_serverglobaledict(self) = oldself;
1108 static void VM_SV_droptofloor (void)
1114 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1116 // assume failure if it returns early
1117 PRVM_G_FLOAT(OFS_RETURN) = 0;
1119 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1120 if (ent == prog->edicts)
1122 VM_Warning("droptofloor: can not modify world entity\n");
1125 if (ent->priv.server->free)
1127 VM_Warning("droptofloor: can not modify free entity\n");
1131 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1134 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1135 if (sv_gameplayfix_unstickentities.integer)
1136 SV_UnstickEntity(ent);
1138 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1139 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1142 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]);
1143 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1144 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1145 VectorSubtract(trace.endpos, offset, trace.endpos);
1146 if (trace.startsolid)
1148 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]);
1149 if (sv_gameplayfix_unstickentities.integer)
1150 SV_UnstickEntity(ent);
1152 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1153 PRVM_serveredictedict(ent, groundentity) = 0;
1154 PRVM_G_FLOAT(OFS_RETURN) = 1;
1156 else if (trace.fraction < 1)
1158 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]);
1159 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1160 if (sv_gameplayfix_unstickentities.integer)
1161 SV_UnstickEntity(ent);
1163 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1164 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1165 PRVM_G_FLOAT(OFS_RETURN) = 1;
1166 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1167 ent->priv.server->suspendedinairflag = true;
1172 if (trace.fraction != 1)
1174 if (trace.fraction < 1)
1175 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1177 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1178 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1179 PRVM_G_FLOAT(OFS_RETURN) = 1;
1180 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1181 ent->priv.server->suspendedinairflag = true;
1190 void(float style, string value) lightstyle
1193 static void VM_SV_lightstyle (void)
1200 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1202 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1203 val = PRVM_G_STRING(OFS_PARM1);
1205 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1206 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1209 // change the string in sv
1210 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1212 // send message to all clients on this server
1213 if (sv.state != ss_active)
1216 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1218 if (client->active && client->netconnection)
1220 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1221 MSG_WriteChar (&client->netconnection->message,style);
1222 MSG_WriteString (&client->netconnection->message, val);
1232 static void VM_SV_checkbottom (void)
1234 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1235 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1243 static void VM_SV_pointcontents (void)
1245 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1246 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1253 Pick a vector for the player to shoot along
1254 vector aim(entity, missilespeed)
1257 static void VM_SV_aim (void)
1259 prvm_edict_t *ent, *check, *bestent;
1260 vec3_t start, dir, end, bestdir;
1263 float dist, bestdist;
1266 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1268 // assume failure if it returns early
1269 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1270 // if sv_aim is so high it can't possibly accept anything, skip out early
1271 if (sv_aim.value >= 1)
1274 ent = PRVM_G_EDICT(OFS_PARM0);
1275 if (ent == prog->edicts)
1277 VM_Warning("aim: can not use world entity\n");
1280 if (ent->priv.server->free)
1282 VM_Warning("aim: can not use free entity\n");
1285 //speed = PRVM_G_FLOAT(OFS_PARM1);
1287 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1290 // try sending a trace straight
1291 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1292 VectorMA (start, 2048, dir, end);
1293 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1294 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1295 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1297 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1302 // try all possible entities
1303 VectorCopy (dir, bestdir);
1304 bestdist = sv_aim.value;
1307 check = PRVM_NEXT_EDICT(prog->edicts);
1308 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1310 prog->xfunction->builtinsprofile++;
1311 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1315 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1316 continue; // don't aim at teammate
1317 for (j=0 ; j<3 ; j++)
1318 end[j] = PRVM_serveredictvector(check, origin)[j]
1319 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1320 VectorSubtract (end, start, dir);
1321 VectorNormalize (dir);
1322 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1323 if (dist < bestdist)
1324 continue; // to far to turn
1325 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1326 if (tr.ent == check)
1327 { // can shoot at this one
1335 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1336 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1337 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1339 VectorNormalize (end);
1340 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1344 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1349 ===============================================================================
1353 ===============================================================================
1356 #define MSG_BROADCAST 0 // unreliable to all
1357 #define MSG_ONE 1 // reliable to one (msg_entity)
1358 #define MSG_ALL 2 // reliable to all
1359 #define MSG_INIT 3 // write to the init string
1360 #define MSG_ENTITY 5
1362 sizebuf_t *WriteDest (void)
1368 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1372 return &sv.datagram;
1375 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1376 entnum = PRVM_NUM_FOR_EDICT(ent);
1377 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1379 VM_Warning ("WriteDest: tried to write to non-client\n");
1380 return &sv.reliable_datagram;
1383 return &svs.clients[entnum-1].netconnection->message;
1386 VM_Warning ("WriteDest: bad destination\n");
1388 return &sv.reliable_datagram;
1394 return sv.writeentitiestoclient_msg;
1400 static void VM_SV_WriteByte (void)
1402 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1403 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1406 static void VM_SV_WriteChar (void)
1408 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1409 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1412 static void VM_SV_WriteShort (void)
1414 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1415 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1418 static void VM_SV_WriteLong (void)
1420 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1421 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1424 static void VM_SV_WriteAngle (void)
1426 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1427 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1430 static void VM_SV_WriteCoord (void)
1432 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1433 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1436 static void VM_SV_WriteString (void)
1438 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1439 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1442 static void VM_SV_WriteUnterminatedString (void)
1444 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1445 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1449 static void VM_SV_WriteEntity (void)
1451 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1452 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1455 // writes a picture as at most size bytes of data
1457 // IMGNAME \0 SIZE(short) IMGDATA
1458 // if failed to read/compress:
1460 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1461 static void VM_SV_WritePicture (void)
1463 const char *imgname;
1467 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1469 imgname = PRVM_G_STRING(OFS_PARM1);
1470 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1474 MSG_WriteString(WriteDest(), imgname);
1475 if(Image_Compress(imgname, size, &buf, &size))
1478 MSG_WriteShort(WriteDest(), size);
1479 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1484 MSG_WriteShort(WriteDest(), 0);
1488 //////////////////////////////////////////////////////////
1490 static void VM_SV_makestatic (void)
1495 // allow 0 parameters due to an id1 qc bug in which this function is used
1496 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1497 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1499 if (prog->argc >= 1)
1500 ent = PRVM_G_EDICT(OFS_PARM0);
1502 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1503 if (ent == prog->edicts)
1505 VM_Warning("makestatic: can not modify world entity\n");
1508 if (ent->priv.server->free)
1510 VM_Warning("makestatic: can not modify free entity\n");
1515 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1520 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1521 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1522 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1524 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1526 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1527 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1528 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1532 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1533 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1534 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1537 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1538 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1539 for (i=0 ; i<3 ; i++)
1541 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1542 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1545 // throw the entity away now
1549 //=============================================================================
1556 static void VM_SV_setspawnparms (void)
1562 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1564 ent = PRVM_G_EDICT(OFS_PARM0);
1565 i = PRVM_NUM_FOR_EDICT(ent);
1566 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1568 Con_Print("tried to setspawnparms on a non-client\n");
1572 // copy spawn parms out of the client_t
1573 client = svs.clients + i-1;
1574 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1575 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1582 Returns a color vector indicating the lighting at the requested point.
1584 (Internal Operation note: actually measures the light beneath the point, just like
1585 the model lighting on the client)
1590 static void VM_SV_getlight (void)
1592 vec3_t ambientcolor, diffusecolor, diffusenormal;
1594 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1595 p = PRVM_G_VECTOR(OFS_PARM0);
1596 VectorClear(ambientcolor);
1597 VectorClear(diffusecolor);
1598 VectorClear(diffusenormal);
1599 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1600 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1601 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1606 unsigned char type; // 1/2/8 or other value if isn't used
1610 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1611 static int vm_customstats_last;
1613 void VM_CustomStats_Clear (void)
1617 Z_Free(vm_customstats);
1618 vm_customstats = NULL;
1619 vm_customstats_last = -1;
1623 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1631 for(i=0; i<vm_customstats_last+1 ;i++)
1633 if(!vm_customstats[i].type)
1635 switch(vm_customstats[i].type)
1637 //string as 16 bytes
1640 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1641 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1642 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1643 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1644 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1646 //float field sent as-is
1648 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1650 //integer value of float field
1652 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1660 // void(float index, float type, .void field) SV_AddStat = #232;
1661 // Set up an auto-sent player stat.
1662 // Client's get thier own fields sent to them. Index may not be less than 32.
1663 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1664 // 1: string (4 stats carrying a total of 16 charactures)
1665 // 2: float (one stat, float converted to an integer for transportation)
1666 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1667 static void VM_SV_AddStat (void)
1672 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1676 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1679 VM_Warning("PF_SV_AddStat: not enough memory\n");
1683 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1684 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1685 off = PRVM_G_INT (OFS_PARM2);
1690 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1693 if(i >= (MAX_CL_STATS-32))
1695 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1698 if(i > (MAX_CL_STATS-32-4) && type == 1)
1700 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1703 vm_customstats[i].type = type;
1704 vm_customstats[i].fieldoffset = off;
1705 if(vm_customstats_last < i)
1706 vm_customstats_last = i;
1713 copies data from one entity to another
1715 copyentity(src, dst)
1718 static void VM_SV_copyentity (void)
1720 prvm_edict_t *in, *out;
1721 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1722 in = PRVM_G_EDICT(OFS_PARM0);
1723 if (in == prog->edicts)
1725 VM_Warning("copyentity: can not read world entity\n");
1728 if (in->priv.server->free)
1730 VM_Warning("copyentity: can not read free entity\n");
1733 out = PRVM_G_EDICT(OFS_PARM1);
1734 if (out == prog->edicts)
1736 VM_Warning("copyentity: can not modify world entity\n");
1739 if (out->priv.server->free)
1741 VM_Warning("copyentity: can not modify free entity\n");
1744 memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
1753 sets the color of a client and broadcasts the update to all connected clients
1755 setcolor(clientent, value)
1758 static void VM_SV_setcolor (void)
1763 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1764 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1765 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1767 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1769 Con_Print("tried to setcolor a non-client\n");
1773 client = svs.clients + entnum-1;
1776 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1777 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1780 if (client->old_colors != client->colors)
1782 client->old_colors = client->colors;
1783 // send notification to all clients
1784 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1785 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1786 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1794 effect(origin, modelname, startframe, framecount, framerate)
1797 static void VM_SV_effect (void)
1801 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1802 s = PRVM_G_STRING(OFS_PARM1);
1805 VM_Warning("effect: no model specified\n");
1809 i = SV_ModelIndex(s, 1);
1812 VM_Warning("effect: model not precached\n");
1816 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1818 VM_Warning("effect: framecount < 1\n");
1822 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1824 VM_Warning("effect: framerate < 1\n");
1828 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));
1831 static void VM_SV_te_blood (void)
1833 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1834 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1836 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1837 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1839 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1840 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1841 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1843 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1844 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1845 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1847 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1848 SV_FlushBroadcastMessages();
1851 static void VM_SV_te_bloodshower (void)
1853 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1854 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1856 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1857 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1859 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1860 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1861 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1863 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1864 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1865 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1869 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1870 SV_FlushBroadcastMessages();
1873 static void VM_SV_te_explosionrgb (void)
1875 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1876 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1877 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1879 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1880 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1881 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1883 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1884 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1885 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1886 SV_FlushBroadcastMessages();
1889 static void VM_SV_te_particlecube (void)
1891 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1892 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1894 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1895 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1909 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1911 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1912 // gravity true/false
1913 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1915 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1916 SV_FlushBroadcastMessages();
1919 static void VM_SV_te_particlerain (void)
1921 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1922 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1924 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1925 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1936 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1939 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1941 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1942 SV_FlushBroadcastMessages();
1945 static void VM_SV_te_particlesnow (void)
1947 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1948 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1950 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1951 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1953 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1954 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1955 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1965 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1967 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1968 SV_FlushBroadcastMessages();
1971 static void VM_SV_te_spark (void)
1973 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1974 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1976 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1977 MSG_WriteByte(&sv.datagram, TE_SPARK);
1979 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1980 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1983 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1984 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1985 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1987 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1988 SV_FlushBroadcastMessages();
1991 static void VM_SV_te_gunshotquad (void)
1993 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1994 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1995 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1997 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1998 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1999 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2000 SV_FlushBroadcastMessages();
2003 static void VM_SV_te_spikequad (void)
2005 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2006 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2007 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2009 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2010 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2011 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2012 SV_FlushBroadcastMessages();
2015 static void VM_SV_te_superspikequad (void)
2017 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2018 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2019 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2021 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2022 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2023 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2024 SV_FlushBroadcastMessages();
2027 static void VM_SV_te_explosionquad (void)
2029 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2030 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2031 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2033 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2034 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2035 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2036 SV_FlushBroadcastMessages();
2039 static void VM_SV_te_smallflash (void)
2041 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2042 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2043 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2045 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2046 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2047 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2048 SV_FlushBroadcastMessages();
2051 static void VM_SV_te_customflash (void)
2053 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2054 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2056 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2057 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2059 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2060 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2061 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2063 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2065 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2067 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2068 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2069 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2070 SV_FlushBroadcastMessages();
2073 static void VM_SV_te_gunshot (void)
2075 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2076 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2077 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2079 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2080 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2081 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2082 SV_FlushBroadcastMessages();
2085 static void VM_SV_te_spike (void)
2087 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2088 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2089 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2091 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2092 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2093 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2094 SV_FlushBroadcastMessages();
2097 static void VM_SV_te_superspike (void)
2099 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2100 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2101 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2103 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2104 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2105 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2106 SV_FlushBroadcastMessages();
2109 static void VM_SV_te_explosion (void)
2111 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2112 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2113 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2115 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2116 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2117 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2118 SV_FlushBroadcastMessages();
2121 static void VM_SV_te_tarexplosion (void)
2123 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2124 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2125 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2127 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2128 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2129 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2130 SV_FlushBroadcastMessages();
2133 static void VM_SV_te_wizspike (void)
2135 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2136 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2137 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2139 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2140 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2141 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2142 SV_FlushBroadcastMessages();
2145 static void VM_SV_te_knightspike (void)
2147 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2148 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2149 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2151 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2152 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2153 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2154 SV_FlushBroadcastMessages();
2157 static void VM_SV_te_lavasplash (void)
2159 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2160 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2161 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2163 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2164 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2165 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2166 SV_FlushBroadcastMessages();
2169 static void VM_SV_te_teleport (void)
2171 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2172 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2173 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2175 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2176 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2177 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2178 SV_FlushBroadcastMessages();
2181 static void VM_SV_te_explosion2 (void)
2183 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2184 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2185 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2187 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2188 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2189 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2191 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2192 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2193 SV_FlushBroadcastMessages();
2196 static void VM_SV_te_lightning1 (void)
2198 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2199 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2200 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2202 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2204 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2205 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2206 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2208 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2209 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2210 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2211 SV_FlushBroadcastMessages();
2214 static void VM_SV_te_lightning2 (void)
2216 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2217 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2218 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2220 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2222 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2223 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2224 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2226 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2227 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2229 SV_FlushBroadcastMessages();
2232 static void VM_SV_te_lightning3 (void)
2234 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2235 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2236 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2238 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2240 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2241 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2242 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2244 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2245 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2246 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2247 SV_FlushBroadcastMessages();
2250 static void VM_SV_te_beam (void)
2252 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2253 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2254 MSG_WriteByte(&sv.datagram, TE_BEAM);
2256 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2258 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2259 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2260 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2262 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2263 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2264 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2265 SV_FlushBroadcastMessages();
2268 static void VM_SV_te_plasmaburn (void)
2270 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2271 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2272 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2273 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2274 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2275 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2276 SV_FlushBroadcastMessages();
2279 static void VM_SV_te_flamejet (void)
2281 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2282 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2283 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2285 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2286 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2287 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2289 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2290 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2291 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2293 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2294 SV_FlushBroadcastMessages();
2297 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2298 //this function originally written by KrimZon, made shorter by LordHavoc
2299 static void VM_SV_clientcommand (void)
2301 client_t *temp_client;
2303 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2305 //find client for this entity
2306 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2307 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2309 Con_Print("PF_clientcommand: entity is not a client\n");
2313 temp_client = host_client;
2314 host_client = svs.clients + i;
2315 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2316 host_client = temp_client;
2319 //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)
2320 static void VM_SV_setattachment (void)
2322 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2323 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2324 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2327 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2329 if (e == prog->edicts)
2331 VM_Warning("setattachment: can not modify world entity\n");
2334 if (e->priv.server->free)
2336 VM_Warning("setattachment: can not modify free entity\n");
2340 if (tagentity == NULL)
2341 tagentity = prog->edicts;
2345 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2347 model = SV_GetModelFromEdict(tagentity);
2350 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2352 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);
2355 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));
2358 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2359 PRVM_serveredictfloat(e, tag_index) = tagindex;
2362 /////////////////////////////////////////
2363 // DP_MD3_TAGINFO extension coded by VorteX
2365 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2369 i = (int)PRVM_serveredictfloat(e, modelindex);
2370 if (i < 1 || i >= MAX_MODELS)
2373 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2376 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2383 Matrix4x4_CreateIdentity(tag_localmatrix);
2385 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2387 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2398 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2401 float pitchsign = 1;
2403 scale = PRVM_serveredictfloat(ent, scale);
2408 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);
2411 pitchsign = SV_GetPitchSign(ent);
2412 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);
2416 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2419 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2421 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2422 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2423 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2424 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2426 *out = identitymatrix;
2430 // Warnings/errors code:
2431 // 0 - normal (everything all-right)
2434 // 3 - null or non-precached model
2435 // 4 - no tags with requested index
2436 // 5 - runaway loop at attachment chain
2437 extern cvar_t cl_bob;
2438 extern cvar_t cl_bobcycle;
2439 extern cvar_t cl_bobup;
2440 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2443 int modelindex, attachloop;
2444 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2447 *out = identitymatrix; // warnings and errors return identical matrix
2449 if (ent == prog->edicts)
2451 if (ent->priv.server->free)
2454 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2455 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2458 model = SV_GetModelByIndex(modelindex);
2460 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2461 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2462 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2464 tagmatrix = identitymatrix;
2465 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2469 if (attachloop >= 256) // prevent runaway looping
2471 // apply transformation by child's tagindex on parent entity and then
2472 // by parent entity itself
2473 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2474 if (ret && attachloop == 0)
2476 SV_GetEntityMatrix(ent, &entitymatrix, false);
2477 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2478 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2479 // next iteration we process the parent entity
2480 if (PRVM_serveredictedict(ent, tag_entity))
2482 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2483 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2490 // RENDER_VIEWMODEL magic
2491 if (PRVM_serveredictedict(ent, viewmodelforclient))
2493 Matrix4x4_Copy(&tagmatrix, out);
2494 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2496 SV_GetEntityMatrix(ent, &entitymatrix, true);
2497 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2500 // Cl_bob, ported from rendering code
2501 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2504 // LordHavoc: this code is *weird*, but not replacable (I think it
2505 // should be done in QC on the server, but oh well, quake is quake)
2506 // LordHavoc: figured out bobup: the time at which the sin is at 180
2507 // degrees (which allows lengthening or squishing the peak or valley)
2508 cycle = sv.time/cl_bobcycle.value;
2509 cycle -= (int)cycle;
2510 if (cycle < cl_bobup.value)
2511 cycle = sin(M_PI * cycle / cl_bobup.value);
2513 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2514 // bob is proportional to velocity in the xy plane
2515 // (don't count Z, or jumping messes it up)
2516 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;
2517 bob = bob*0.3 + bob*0.7*cycle;
2518 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2525 //float(entity ent, string tagname) gettagindex;
2527 static void VM_SV_gettagindex (void)
2530 const char *tag_name;
2533 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2535 ent = PRVM_G_EDICT(OFS_PARM0);
2536 tag_name = PRVM_G_STRING(OFS_PARM1);
2538 if (ent == prog->edicts)
2540 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2543 if (ent->priv.server->free)
2545 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2550 if (!SV_GetModelFromEdict(ent))
2551 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2554 tag_index = SV_GetTagIndex(ent, tag_name);
2556 if(developer_extra.integer)
2557 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2559 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2562 //vector(entity ent, float tagindex) gettaginfo;
2563 static void VM_SV_gettaginfo (void)
2567 matrix4x4_t tag_matrix;
2568 matrix4x4_t tag_localmatrix;
2570 const char *tagname;
2572 vec3_t fo, le, up, trans;
2573 const dp_model_t *model;
2575 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2577 e = PRVM_G_EDICT(OFS_PARM0);
2578 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2580 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2581 Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
2582 VectorScale(le, -1, PRVM_serverglobalvector(v_right));
2583 model = SV_GetModelFromEdict(e);
2584 VM_GenerateFrameGroupBlend(e->priv.server->framegroupblend, e);
2585 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
2586 VM_UpdateEdictSkeleton(e, model, e->priv.server->frameblend);
2587 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2588 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2590 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2591 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(tagname) : 0;
2592 VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
2593 VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
2594 VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
2595 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2600 VM_Warning("gettagindex: can't affect world entity\n");
2603 VM_Warning("gettagindex: can't affect free entity\n");
2606 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2609 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2612 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2617 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2618 static void VM_SV_dropclient (void)
2621 client_t *oldhostclient;
2622 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2623 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2624 if (clientnum < 0 || clientnum >= svs.maxclients)
2626 VM_Warning("dropclient: not a client\n");
2629 if (!svs.clients[clientnum].active)
2631 VM_Warning("dropclient: that client slot is not connected\n");
2634 oldhostclient = host_client;
2635 host_client = svs.clients + clientnum;
2636 SV_DropClient(false);
2637 host_client = oldhostclient;
2640 //entity() spawnclient (DP_SV_BOTCLIENT)
2641 static void VM_SV_spawnclient (void)
2645 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2646 prog->xfunction->builtinsprofile += 2;
2648 for (i = 0;i < svs.maxclients;i++)
2650 if (!svs.clients[i].active)
2652 prog->xfunction->builtinsprofile += 100;
2653 SV_ConnectClient (i, NULL);
2654 // this has to be set or else ClientDisconnect won't be called
2655 // we assume the qc will call ClientConnect...
2656 svs.clients[i].clientconnectcalled = true;
2657 ed = PRVM_EDICT_NUM(i + 1);
2661 VM_RETURN_EDICT(ed);
2664 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2665 static void VM_SV_clienttype (void)
2668 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2669 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2670 if (clientnum < 0 || clientnum >= svs.maxclients)
2671 PRVM_G_FLOAT(OFS_RETURN) = 3;
2672 else if (!svs.clients[clientnum].active)
2673 PRVM_G_FLOAT(OFS_RETURN) = 0;
2674 else if (svs.clients[clientnum].netconnection)
2675 PRVM_G_FLOAT(OFS_RETURN) = 1;
2677 PRVM_G_FLOAT(OFS_RETURN) = 2;
2684 string(string key) serverkey
2687 void VM_SV_serverkey(void)
2689 char string[VM_STRINGTEMP_LENGTH];
2690 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2691 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2692 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2695 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2696 static void VM_SV_setmodelindex (void)
2701 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2703 e = PRVM_G_EDICT(OFS_PARM0);
2704 if (e == prog->edicts)
2706 VM_Warning("setmodelindex: can not modify world entity\n");
2709 if (e->priv.server->free)
2711 VM_Warning("setmodelindex: can not modify free entity\n");
2714 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2715 if (i <= 0 || i >= MAX_MODELS)
2717 VM_Warning("setmodelindex: invalid modelindex\n");
2720 if (!sv.model_precache[i][0])
2722 VM_Warning("setmodelindex: model not precached\n");
2726 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
2727 PRVM_serveredictfloat(e, modelindex) = i;
2729 mod = SV_GetModelByIndex(i);
2733 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2734 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2736 SetMinMaxSize (e, quakemins, quakemaxs, true);
2739 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2742 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2743 static void VM_SV_modelnameforindex (void)
2746 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2748 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2750 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2751 if (i <= 0 || i >= MAX_MODELS)
2753 VM_Warning("modelnameforindex: invalid modelindex\n");
2756 if (!sv.model_precache[i][0])
2758 VM_Warning("modelnameforindex: model not precached\n");
2762 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2765 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2766 static void VM_SV_particleeffectnum (void)
2769 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2770 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2773 PRVM_G_FLOAT(OFS_RETURN) = i;
2776 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2777 static void VM_SV_trailparticles (void)
2779 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2781 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2784 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2785 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2786 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2787 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2788 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2789 SV_FlushBroadcastMessages();
2792 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2793 static void VM_SV_pointparticles (void)
2795 int effectnum, count;
2797 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2799 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2802 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2803 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2804 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2805 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2806 if (count == 1 && !VectorLength2(vel))
2809 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2810 MSG_WriteShort(&sv.datagram, effectnum);
2811 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2815 // 1+2+12+12+2=29 bytes
2816 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2817 MSG_WriteShort(&sv.datagram, effectnum);
2818 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2819 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2820 MSG_WriteShort(&sv.datagram, count);
2823 SV_FlushBroadcastMessages();
2826 //PF_setpause, // void(float pause) setpause = #531;
2827 static void VM_SV_setpause(void) {
2829 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2830 if (pauseValue != 0) { //pause the game
2832 sv.pausedstart = Sys_DoubleTime();
2833 } else { //disable pause, in case it was enabled
2834 if (sv.paused != 0) {
2839 // send notification to all clients
2840 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2841 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2844 // #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.
2845 static void VM_SV_skel_create(void)
2847 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2848 dp_model_t *model = SV_GetModelByIndex(modelindex);
2849 skeleton_t *skeleton;
2851 PRVM_G_FLOAT(OFS_RETURN) = 0;
2852 if (!model || !model->num_bones)
2854 for (i = 0;i < MAX_EDICTS;i++)
2855 if (!prog->skeletons[i])
2857 if (i == MAX_EDICTS)
2859 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2860 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2861 skeleton->model = model;
2862 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2863 // initialize to identity matrices
2864 for (i = 0;i < skeleton->model->num_bones;i++)
2865 skeleton->relativetransforms[i] = identitymatrix;
2868 // #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
2869 static void VM_SV_skel_build(void)
2871 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2872 skeleton_t *skeleton;
2873 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2874 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2875 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2876 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2877 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2878 dp_model_t *model = SV_GetModelByIndex(modelindex);
2883 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2884 frameblend_t frameblend[MAX_FRAMEBLENDS];
2885 matrix4x4_t blendedmatrix;
2887 PRVM_G_FLOAT(OFS_RETURN) = 0;
2888 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2890 firstbone = max(0, firstbone);
2891 lastbone = min(lastbone, model->num_bones - 1);
2892 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2893 VM_GenerateFrameGroupBlend(framegroupblend, ed);
2894 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
2895 blendfrac = 1.0f - retainfrac;
2896 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2897 frameblend[numblends].lerp *= blendfrac;
2898 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2900 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2901 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2902 for (blendindex = 0;blendindex < numblends;blendindex++)
2904 Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2905 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2907 skeleton->relativetransforms[bonenum] = blendedmatrix;
2909 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2912 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2913 static void VM_SV_skel_get_numbones(void)
2915 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2916 skeleton_t *skeleton;
2917 PRVM_G_FLOAT(OFS_RETURN) = 0;
2918 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2920 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2923 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2924 static void VM_SV_skel_get_bonename(void)
2926 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2927 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2928 skeleton_t *skeleton;
2929 PRVM_G_INT(OFS_RETURN) = 0;
2930 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2932 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2934 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(skeleton->model->data_bones[bonenum].name);
2937 // #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)
2938 static void VM_SV_skel_get_boneparent(void)
2940 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2941 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2942 skeleton_t *skeleton;
2943 PRVM_G_FLOAT(OFS_RETURN) = 0;
2944 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2946 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2948 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2951 // #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
2952 static void VM_SV_skel_find_bone(void)
2954 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2955 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2956 skeleton_t *skeleton;
2957 PRVM_G_FLOAT(OFS_RETURN) = 0;
2958 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2960 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2963 // #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)
2964 static void VM_SV_skel_get_bonerel(void)
2966 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2967 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2968 skeleton_t *skeleton;
2970 vec3_t forward, left, up, origin;
2971 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2972 VectorClear(PRVM_clientglobalvector(v_forward));
2973 VectorClear(PRVM_clientglobalvector(v_right));
2974 VectorClear(PRVM_clientglobalvector(v_up));
2975 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2977 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2979 matrix = skeleton->relativetransforms[bonenum];
2980 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2981 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2982 VectorNegate(left, PRVM_clientglobalvector(v_right));
2983 VectorCopy(up, PRVM_clientglobalvector(v_up));
2984 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2987 // #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)
2988 static void VM_SV_skel_get_boneabs(void)
2990 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2991 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2992 skeleton_t *skeleton;
2995 vec3_t forward, left, up, origin;
2996 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2997 VectorClear(PRVM_clientglobalvector(v_forward));
2998 VectorClear(PRVM_clientglobalvector(v_right));
2999 VectorClear(PRVM_clientglobalvector(v_up));
3000 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3002 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3004 matrix = skeleton->relativetransforms[bonenum];
3005 // convert to absolute
3006 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3009 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3011 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3012 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3013 VectorNegate(left, PRVM_clientglobalvector(v_right));
3014 VectorCopy(up, PRVM_clientglobalvector(v_up));
3015 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3018 // #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)
3019 static void VM_SV_skel_set_bone(void)
3021 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3022 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3023 vec3_t forward, left, up, origin;
3024 skeleton_t *skeleton;
3026 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3028 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3030 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3031 VectorNegate(PRVM_clientglobalvector(v_right), left);
3032 VectorCopy(PRVM_clientglobalvector(v_up), up);
3033 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3034 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3035 skeleton->relativetransforms[bonenum] = matrix;
3038 // #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)
3039 static void VM_SV_skel_mul_bone(void)
3041 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3042 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3043 vec3_t forward, left, up, origin;
3044 skeleton_t *skeleton;
3047 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3049 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3051 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3052 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3053 VectorNegate(PRVM_clientglobalvector(v_right), left);
3054 VectorCopy(PRVM_clientglobalvector(v_up), up);
3055 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3056 temp = skeleton->relativetransforms[bonenum];
3057 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3060 // #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)
3061 static void VM_SV_skel_mul_bones(void)
3063 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3064 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3065 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3067 vec3_t forward, left, up, origin;
3068 skeleton_t *skeleton;
3071 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3073 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3074 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3075 VectorNegate(PRVM_clientglobalvector(v_right), left);
3076 VectorCopy(PRVM_clientglobalvector(v_up), up);
3077 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3078 firstbone = max(0, firstbone);
3079 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3080 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3082 temp = skeleton->relativetransforms[bonenum];
3083 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3087 // #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
3088 static void VM_SV_skel_copybones(void)
3090 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3091 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3092 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3093 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3095 skeleton_t *skeletondst;
3096 skeleton_t *skeletonsrc;
3097 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3099 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3101 firstbone = max(0, firstbone);
3102 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3103 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3104 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3105 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3108 // #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)
3109 static void VM_SV_skel_delete(void)
3111 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3112 skeleton_t *skeleton;
3113 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3116 prog->skeletons[skeletonindex] = NULL;
3119 // #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
3120 static void VM_SV_frameforname(void)
3122 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3123 dp_model_t *model = SV_GetModelByIndex(modelindex);
3124 const char *name = PRVM_G_STRING(OFS_PARM1);
3126 PRVM_G_FLOAT(OFS_RETURN) = -1;
3127 if (!model || !model->animscenes)
3129 for (i = 0;i < model->numframes;i++)
3131 if (!strcasecmp(model->animscenes[i].name, name))
3133 PRVM_G_FLOAT(OFS_RETURN) = i;
3139 // #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.
3140 static void VM_SV_frameduration(void)
3142 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3143 dp_model_t *model = SV_GetModelByIndex(modelindex);
3144 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3145 PRVM_G_FLOAT(OFS_RETURN) = 0;
3146 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3148 if (model->animscenes[framenum].framerate)
3149 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3153 prvm_builtin_t vm_sv_builtins[] = {
3154 NULL, // #0 NULL function (not callable) (QUAKE)
3155 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3156 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3157 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3158 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3159 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3160 VM_break, // #6 void() break (QUAKE)
3161 VM_random, // #7 float() random (QUAKE)
3162 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3163 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3164 VM_error, // #10 void(string e) error (QUAKE)
3165 VM_objerror, // #11 void(string e) objerror (QUAKE)
3166 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3167 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3168 VM_spawn, // #14 entity() spawn (QUAKE)
3169 VM_remove, // #15 void(entity e) remove (QUAKE)
3170 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3171 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3172 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3173 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3174 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3175 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3176 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3177 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3178 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3179 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3180 VM_ftos, // #26 string(float f) ftos (QUAKE)
3181 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3182 VM_coredump, // #28 void() coredump (QUAKE)
3183 VM_traceon, // #29 void() traceon (QUAKE)
3184 VM_traceoff, // #30 void() traceoff (QUAKE)
3185 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3186 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3187 NULL, // #33 (QUAKE)
3188 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3189 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3190 VM_rint, // #36 float(float v) rint (QUAKE)
3191 VM_floor, // #37 float(float v) floor (QUAKE)
3192 VM_ceil, // #38 float(float v) ceil (QUAKE)
3193 NULL, // #39 (QUAKE)
3194 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3195 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3196 NULL, // #42 (QUAKE)
3197 VM_fabs, // #43 float(float f) fabs (QUAKE)
3198 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3199 VM_cvar, // #45 float(string s) cvar (QUAKE)
3200 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3201 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3202 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3203 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3204 NULL, // #50 (QUAKE)
3205 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3206 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3207 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3208 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3209 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3210 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3211 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3212 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3213 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3214 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3215 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3216 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3217 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3218 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3219 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3220 NULL, // #66 (QUAKE)
3221 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3222 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3223 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3224 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3225 NULL, // #71 (QUAKE)
3226 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3227 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3228 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3229 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3230 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3231 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3232 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3233 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3234 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3235 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3236 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3237 NULL, // #83 (QUAKE)
3238 NULL, // #84 (QUAKE)
3239 NULL, // #85 (QUAKE)
3240 NULL, // #86 (QUAKE)
3241 NULL, // #87 (QUAKE)
3242 NULL, // #88 (QUAKE)
3243 NULL, // #89 (QUAKE)
3244 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3245 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3246 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3247 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3248 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3249 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3250 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3251 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3252 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3253 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3254 // FrikaC and Telejano range #100-#199
3265 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3266 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3267 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3268 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3269 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3270 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3271 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3272 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3273 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3274 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3355 // FTEQW range #200-#299
3374 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3377 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3378 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3379 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3380 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3381 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3382 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3383 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3384 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3385 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3386 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3388 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3396 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3419 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.
3420 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
3421 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3422 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3423 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)
3424 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
3425 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)
3426 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)
3427 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)
3428 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)
3429 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)
3430 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
3431 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)
3432 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
3433 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.
3456 // CSQC range #300-#399
3457 NULL, // #300 void() clearscene (EXT_CSQC)
3458 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3459 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3460 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3461 NULL, // #304 void() renderscene (EXT_CSQC)
3462 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3463 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3464 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3465 NULL, // #308 void() R_EndPolygon
3467 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3468 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3472 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3473 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3474 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3475 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3476 NULL, // #319 void(string name) freepic (EXT_CSQC)
3477 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3478 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3479 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3480 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3481 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3482 NULL, // #325 void(void) drawresetcliparea
3487 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3488 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3489 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3490 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3491 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3492 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3493 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3494 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3495 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3496 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3497 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3498 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3499 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3500 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3501 NULL, // #344 vector() getmousepos (EXT_CSQC)
3502 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3503 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3504 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3505 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3506 NULL, // #349 float() isdemo (EXT_CSQC)
3507 VM_isserver, // #350 float() isserver (EXT_CSQC)
3508 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3509 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3510 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3511 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3517 NULL, // #360 float() readbyte (EXT_CSQC)
3518 NULL, // #361 float() readchar (EXT_CSQC)
3519 NULL, // #362 float() readshort (EXT_CSQC)
3520 NULL, // #363 float() readlong (EXT_CSQC)
3521 NULL, // #364 float() readcoord (EXT_CSQC)
3522 NULL, // #365 float() readangle (EXT_CSQC)
3523 NULL, // #366 string() readstring (EXT_CSQC)
3524 NULL, // #367 float() readfloat (EXT_CSQC)
3557 // LordHavoc's range #400-#499
3558 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3559 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3560 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3561 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3562 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3563 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3564 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3565 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3566 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)
3567 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3568 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3569 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3570 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3571 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3572 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3573 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3574 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3575 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3576 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3577 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3578 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3579 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3580 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3581 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3582 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3583 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3584 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3585 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3586 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3587 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3588 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3589 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3590 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3591 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3592 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3593 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3594 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3595 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3596 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3597 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3598 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3599 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3600 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3601 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3602 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3603 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3604 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3605 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3606 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3607 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3608 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3609 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3610 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3611 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3612 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3613 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3614 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3615 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3617 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3618 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3619 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3620 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3621 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3622 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3623 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3624 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3625 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3626 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3627 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3629 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3630 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3631 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3632 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3633 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3634 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3635 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3636 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3637 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3638 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3639 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3640 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3641 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3642 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3643 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3644 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3652 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3653 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3654 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3655 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3656 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3657 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3658 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3659 VM_SV_WritePicture, // #501
3661 VM_whichpack, // #503 string(string) whichpack = #503;
3668 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3669 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3670 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3671 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)
3672 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3673 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3674 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3675 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3676 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3677 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3687 VM_loadfromdata, // #529
3688 VM_loadfromfile, // #530
3689 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3691 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3692 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3698 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3699 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3700 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3763 VM_callfunction, // #605
3764 VM_writetofile, // #606
3765 VM_isfunction, // #607
3771 VM_parseentitydata, // #613
3782 VM_SV_getextresponse, // #624 string getextresponse(void)
3785 VM_sprintf, // #627 string sprintf(string format, ...)
3786 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3787 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3791 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3793 void VM_SV_Cmd_Init(void)
3798 void VM_SV_Cmd_Reset(void)
3800 World_End(&sv.world);
3801 if(PRVM_serverfunction(SV_Shutdown))
3803 func_t s = PRVM_serverfunction(SV_Shutdown);
3804 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3805 PRVM_ExecuteProgram(s,"SV_Shutdown() required");