6 //============================================================================
11 const char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
24 "DP_CSQC_ENTITYWORLDOBJECT "
25 "DP_CSQC_ENTITYMODELLIGHT "
26 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
28 "DP_CSQC_MINFPS_QUALITY "
29 "DP_CSQC_MULTIFRAME_INTERPOLATION "
30 "DP_CSQC_BOXPARTICLES "
31 "DP_CSQC_SPAWNPARTICLE "
32 "DP_CSQC_QUERYRENDERENTITY "
33 "DP_CSQC_ROTATEMOVES "
35 "DP_CSQC_V_CALCREFDEF_WIP1 "
36 "DP_CSQC_V_CALCREFDEF_WIP2 "
40 "DP_EF_DYNAMICMODELLIGHT "
49 "DP_EF_RESTARTANIM_BIT "
54 "DP_ENT_CUSTOMCOLORMAP "
55 "DP_ENT_EXTERIORMODELTOCLIENT "
58 "DP_ENT_LOWPRECISION "
60 "DP_ENT_TRAILEFFECTNUM "
62 "DP_GFX_EXTERNALTEXTURES "
63 "DP_GFX_EXTERNALTEXTURES_PERMAP "
65 "DP_GFX_MODEL_INTERPOLATION "
66 "DP_GFX_QUAKE3MODELTAGS "
70 "DP_GFX_FONTS_FREETYPE "
72 "DP_FONT_VARIABLEWIDTH "
74 "DP_HALFLIFE_MAP_CVAR "
77 "DP_LIGHTSTYLE_STATICVALUE "
81 "DP_MOVETYPEBOUNCEMISSILE "
82 "DP_MOVETYPEFLYWORLDONLY "
85 "DP_QC_ASINACOSATANATAN2TAN "
91 "DP_QC_CVAR_DEFSTRING "
92 "DP_QC_CVAR_DESCRIPTION "
96 "DP_QC_DIGEST_SHA256 "
101 "DP_QC_EXTRESPONSEPACKET "
103 "DP_QC_FINDCHAINFLAGS "
104 "DP_QC_FINDCHAINFLOAT "
105 "DP_QC_FINDCHAIN_TOFIELD "
111 "DP_QC_GETSURFACETRIANGLE "
112 "DP_QC_GETSURFACEPOINTATTRIBUTE "
114 "DP_QC_GETTAGINFO_BONEPROPERTIES "
116 "DP_QC_GETTIME_CDTRACK "
120 "DP_QC_MULTIPLETEMPSTRINGS "
121 "DP_QC_NUM_FOR_EDICT "
123 "DP_QC_SINCOSSQRTPOW "
126 "DP_QC_STRINGBUFFERS "
127 "DP_QC_STRINGBUFFERS_CVARLIST "
128 "DP_QC_STRINGBUFFERS_EXT_WIP "
129 "DP_QC_STRINGCOLORFUNCTIONS "
130 "DP_QC_STRING_CASE_FUNCTIONS "
132 "DP_QC_TOKENIZEBYSEPARATOR "
133 "DP_QC_TOKENIZE_CONSOLE "
136 "DP_QC_TRACE_MOVETYPE_HITMODEL "
137 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
138 "DP_QC_UNLIMITEDTEMPSTRINGS "
142 "DP_QC_VECTOANGLES_WITH_ROLL "
143 "DP_QC_VECTORVECTORS "
150 "DP_SKELETONOBJECTS "
151 "DP_SND_DIRECTIONLESSATTNNONE "
153 "DP_SND_SOUND7_WIP1 "
154 "DP_SND_SOUND7_WIP2 "
158 "DP_SND_GETSOUNDTIME "
160 "DP_VIDEO_SUBTITLES "
164 "DP_SV_BOUNCEFACTOR "
165 "DP_SV_CLIENTCAMERA "
166 "DP_SV_CLIENTCOLORS "
169 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
170 "DP_SV_DISCARDABLEDEMO "
171 "DP_SV_DRAWONLYTOCLIENT "
174 "DP_SV_ENTITYCONTENTSTRANSITION "
175 "DP_SV_MODELFLAGS_AS_EFFECTS "
176 "DP_SV_MOVETYPESTEP_LANDEVENT "
178 "DP_SV_NODRAWTOCLIENT "
179 "DP_SV_ONENTITYNOSPAWNFUNCTION "
180 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
182 "DP_SV_PING_PACKETLOSS "
183 "DP_SV_PLAYERPHYSICS "
185 "DP_SV_POINTPARTICLES "
187 "DP_SV_PRECACHEANYTIME "
191 "DP_SV_ROTATINGBMODEL "
195 "DP_SV_SPAWNFUNC_PREFIX "
196 "DP_SV_WRITEPICTURE "
197 "DP_SV_WRITEUNTERMINATEDSTRING "
201 "DP_TE_EXPLOSIONRGB "
203 "DP_TE_PARTICLECUBE "
204 "DP_TE_PARTICLERAIN "
205 "DP_TE_PARTICLESNOW "
207 "DP_TE_QUADEFFECTS1 "
210 "DP_TE_STANDARDEFFECTBUILTINS "
211 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
215 "FTE_CSQC_SKELETONOBJECTS "
218 "KRIMZON_SV_PARSECLIENTCOMMAND "
221 "NEXUIZ_PLAYERMODEL "
223 "PRYDON_CLIENTCURSOR "
224 "TENEBRAE_GFX_DLIGHTS "
227 //"EXT_CSQC " // not ready yet
234 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.
236 setorigin (entity, origin)
239 static void VM_SV_setorigin(prvm_prog_t *prog)
243 VM_SAFEPARMCOUNT(2, VM_setorigin);
245 e = PRVM_G_EDICT(OFS_PARM0);
246 if (e == prog->edicts)
248 VM_Warning(prog, "setorigin: can not modify world entity\n");
251 if (e->priv.server->free)
253 VM_Warning(prog, "setorigin: can not modify free entity\n");
256 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), PRVM_serveredictvector(e, origin));
257 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
258 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
262 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
263 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qboolean rotate)
267 for (i=0 ; i<3 ; i++)
269 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
271 // set derived values
272 VectorCopy (min, PRVM_serveredictvector(e, mins));
273 VectorCopy (max, PRVM_serveredictvector(e, maxs));
274 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
283 the size box is rotated by the current angle
284 LordHavoc: no it isn't...
286 setsize (entity, minvector, maxvector)
289 static void VM_SV_setsize(prvm_prog_t *prog)
294 VM_SAFEPARMCOUNT(3, VM_setsize);
296 e = PRVM_G_EDICT(OFS_PARM0);
297 if (e == prog->edicts)
299 VM_Warning(prog, "setsize: can not modify world entity\n");
302 if (e->priv.server->free)
304 VM_Warning(prog, "setsize: can not modify free entity\n");
307 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), mins);
308 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), maxs);
309 SetMinMaxSize(prog, e, mins, maxs, false);
317 setmodel(entity, model)
320 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
321 static void VM_SV_setmodel(prvm_prog_t *prog)
327 VM_SAFEPARMCOUNT(2, VM_setmodel);
329 e = PRVM_G_EDICT(OFS_PARM0);
330 if (e == prog->edicts)
332 VM_Warning(prog, "setmodel: can not modify world entity\n");
335 if (e->priv.server->free)
337 VM_Warning(prog, "setmodel: can not modify free entity\n");
340 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
341 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
342 PRVM_serveredictfloat(e, modelindex) = i;
344 mod = SV_GetModelByIndex(i);
348 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
349 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
351 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
354 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
361 single print to a specific client
363 sprint(clientent, value)
366 static void VM_SV_sprint(prvm_prog_t *prog)
370 char string[VM_STRINGTEMP_LENGTH];
372 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
374 VM_VarString(prog, 1, string, sizeof(string));
376 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
377 // LordHavoc: div0 requested that sprintto world operate like print
384 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
386 VM_Warning(prog, "tried to centerprint to a non-client\n");
390 client = svs.clients + entnum-1;
391 if (!client->netconnection)
394 MSG_WriteChar(&client->netconnection->message,svc_print);
395 MSG_WriteString(&client->netconnection->message, string);
403 single print to a specific client
405 centerprint(clientent, value)
408 static void VM_SV_centerprint(prvm_prog_t *prog)
412 char string[VM_STRINGTEMP_LENGTH];
414 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
416 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
418 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
420 VM_Warning(prog, "tried to centerprint to a non-client\n");
424 client = svs.clients + entnum-1;
425 if (!client->netconnection)
428 VM_VarString(prog, 1, string, sizeof(string));
429 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
430 MSG_WriteString(&client->netconnection->message, string);
437 particle(origin, color, count)
440 static void VM_SV_particle(prvm_prog_t *prog)
446 VM_SAFEPARMCOUNT(4, VM_SV_particle);
448 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
449 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
450 color = (int)PRVM_G_FLOAT(OFS_PARM2);
451 count = (int)PRVM_G_FLOAT(OFS_PARM3);
452 SV_StartParticle (org, dir, color, count);
462 static void VM_SV_ambientsound(prvm_prog_t *prog)
466 prvm_vec_t vol, attenuation;
469 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
471 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
472 samp = PRVM_G_STRING(OFS_PARM1);
473 vol = PRVM_G_FLOAT(OFS_PARM2);
474 attenuation = PRVM_G_FLOAT(OFS_PARM3);
476 // check to see if samp was properly precached
477 soundnum = SV_SoundIndex(samp, 1);
485 // add an svc_spawnambient command to the level signon packet
488 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
490 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
492 MSG_WriteVector(&sv.signon, pos, sv.protocol);
494 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
495 MSG_WriteShort (&sv.signon, soundnum);
497 MSG_WriteByte (&sv.signon, soundnum);
499 MSG_WriteByte (&sv.signon, (int)(vol*255));
500 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
508 Each entity can have eight independant sound sources, like voice,
511 Channel 0 is an auto-allocate channel, the others override anything
512 already running on that entity/channel pair.
514 An attenuation of 0 will play full volume everywhere in the level.
515 Larger attenuations will drop off.
519 static void VM_SV_sound(prvm_prog_t *prog)
523 prvm_edict_t *entity;
529 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
531 entity = PRVM_G_EDICT(OFS_PARM0);
532 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
533 sample = PRVM_G_STRING(OFS_PARM2);
534 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
537 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
541 attenuation = PRVM_G_FLOAT(OFS_PARM4);
545 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
550 if(channel >= 8 && channel <= 15) // weird QW feature
552 flags |= CHANNELFLAG_RELIABLE;
558 // LordHavoc: we only let the qc set certain flags, others are off-limits
559 flags = (int)PRVM_G_FLOAT(OFS_PARM6) & (CHANNELFLAG_RELIABLE | CHANNELFLAG_FORCELOOP | CHANNELFLAG_PAUSED);
562 if (volume < 0 || volume > 255)
564 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
568 if (attenuation < 0 || attenuation > 4)
570 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
574 channel = CHAN_USER2ENGINE(channel);
576 if (!IS_CHAN(channel))
578 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
582 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANNELFLAG_RELIABLE, pitchchange);
589 Follows the same logic as VM_SV_sound, except instead of
590 an entity, an origin for the sound is provided, and channel
591 is omitted (since no entity is being tracked).
595 static void VM_SV_pointsound(prvm_prog_t *prog)
603 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
605 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
606 sample = PRVM_G_STRING(OFS_PARM1);
607 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
608 attenuation = PRVM_G_FLOAT(OFS_PARM3);
609 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
611 if (volume < 0 || volume > 255)
613 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
617 if (attenuation < 0 || attenuation > 4)
619 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
623 SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
630 Used for use tracing and shot targeting
631 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
632 if the tryents flag is set.
634 traceline (vector1, vector2, movetype, ignore)
637 static void VM_SV_traceline(prvm_prog_t *prog)
644 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
646 prog->xfunction->builtinsprofile += 30;
648 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
649 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), v2);
650 move = (int)PRVM_G_FLOAT(OFS_PARM2);
651 ent = PRVM_G_EDICT(OFS_PARM3);
653 if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_IS_NAN(v2[2]))
654 prog->error_cmd("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
656 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
658 VM_SetTraceGlobals(prog, &trace);
666 Used for use tracing and shot targeting
667 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
668 if the tryents flag is set.
670 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
673 // LordHavoc: added this for my own use, VERY useful, similar to traceline
674 static void VM_SV_tracebox(prvm_prog_t *prog)
676 vec3_t v1, v2, m1, m2;
681 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
683 prog->xfunction->builtinsprofile += 30;
685 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
686 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), m1);
687 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), m2);
688 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), v2);
689 move = (int)PRVM_G_FLOAT(OFS_PARM4);
690 ent = PRVM_G_EDICT(OFS_PARM5);
692 if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_IS_NAN(v2[2]))
693 prog->error_cmd("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
695 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
697 VM_SetTraceGlobals(prog, &trace);
700 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
704 vec3_t move, end, tossentorigin, tossentmins, tossentmaxs;
705 vec3_t original_origin;
706 vec3_t original_velocity;
707 vec3_t original_angles;
708 vec3_t original_avelocity;
711 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
712 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
713 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
714 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
716 gravity = PRVM_serveredictfloat(tossent, gravity);
719 gravity *= sv_gravity.value * 0.025;
721 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
723 SV_CheckVelocity (tossent);
724 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
725 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
726 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
727 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
728 VectorCopy(PRVM_serveredictvector(tossent, origin), tossentorigin);
729 VectorCopy(PRVM_serveredictvector(tossent, mins), tossentmins);
730 VectorCopy(PRVM_serveredictvector(tossent, maxs), tossentmaxs);
731 trace = SV_TraceBox(tossentorigin, tossentmins, tossentmaxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
732 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
733 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
735 if (trace.fraction < 1)
739 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
740 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
741 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
742 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
747 static void VM_SV_tracetoss(prvm_prog_t *prog)
751 prvm_edict_t *ignore;
753 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
755 prog->xfunction->builtinsprofile += 600;
757 ent = PRVM_G_EDICT(OFS_PARM0);
758 if (ent == prog->edicts)
760 VM_Warning(prog, "tracetoss: can not use world entity\n");
763 ignore = PRVM_G_EDICT(OFS_PARM1);
765 trace = SV_Trace_Toss(prog, ent, ignore);
767 VM_SetTraceGlobals(prog, &trace);
770 //============================================================================
772 static int checkpvsbytes;
773 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
775 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
781 // cycle to the next one
783 check = bound(1, check, svs.maxclients);
784 if (check == svs.maxclients)
792 prog->xfunction->builtinsprofile++;
794 if (i == svs.maxclients+1)
796 // look up the client's edict
797 ent = PRVM_EDICT_NUM(i);
798 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
799 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
801 // found a valid client (possibly the same one again)
805 // get the PVS for the entity
806 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
808 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
809 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
818 Returns a client (or object that has a client enemy) that would be a
821 If there is more than one valid option, they are cycled each frame
823 If (self.origin + self.viewofs) is not in the PVS of the current target,
824 it is not returned at all.
829 int c_invis, c_notvis;
830 static void VM_SV_checkclient(prvm_prog_t *prog)
832 prvm_edict_t *ent, *self;
835 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
837 // find a new check if on a new frame
838 if (sv.time - sv.lastchecktime >= 0.1)
840 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
841 sv.lastchecktime = sv.time;
844 // return check if it might be visible
845 ent = PRVM_EDICT_NUM(sv.lastcheck);
846 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
848 VM_RETURN_EDICT(prog->edicts);
852 // if current entity can't possibly see the check entity, return 0
853 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
854 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
855 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
858 VM_RETURN_EDICT(prog->edicts);
862 // might be able to see it
864 VM_RETURN_EDICT(ent);
867 //============================================================================
873 Checks if an entity is in a point's PVS.
874 Should be fast but can be inexact.
876 float checkpvs(vector viewpos, entity viewee) = #240;
879 static void VM_SV_checkpvs(prvm_prog_t *prog)
881 vec3_t viewpos, absmin, absmax;
882 prvm_edict_t *viewee;
887 unsigned char fatpvs[MAX_MAP_LEAFS/8];
890 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
891 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
892 viewee = PRVM_G_EDICT(OFS_PARM1);
894 if(viewee->priv.server->free)
896 VM_Warning(prog, "checkpvs: can not check free entity\n");
897 PRVM_G_FLOAT(OFS_RETURN) = 4;
902 if(!sv.worldmodel || !sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
904 // no PVS support on this worldmodel... darn
905 PRVM_G_FLOAT(OFS_RETURN) = 3;
908 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
911 // viewpos isn't in any PVS... darn
912 PRVM_G_FLOAT(OFS_RETURN) = 2;
915 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
916 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
917 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, absmin, absmax);
919 // using fat PVS like FTEQW does (slow)
920 if(!sv.worldmodel || !sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
922 // no PVS support on this worldmodel... darn
923 PRVM_G_FLOAT(OFS_RETURN) = 3;
926 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
929 // viewpos isn't in any PVS... darn
930 PRVM_G_FLOAT(OFS_RETURN) = 2;
933 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
934 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
935 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, absmin, absmax);
944 Sends text over to the client's execution buffer
946 stuffcmd (clientent, value, ...)
949 static void VM_SV_stuffcmd(prvm_prog_t *prog)
953 char string[VM_STRINGTEMP_LENGTH];
955 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
957 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
958 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
960 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
964 VM_VarString(prog, 1, string, sizeof(string));
967 host_client = svs.clients + entnum-1;
968 Host_ClientCommands ("%s", string);
976 Returns a chain of entities that have origins within a spherical area
978 findradius (origin, radius)
981 static void VM_SV_findradius(prvm_prog_t *prog)
983 prvm_edict_t *ent, *chain;
984 vec_t radius, radius2;
985 vec3_t org, eorg, mins, maxs;
988 static prvm_edict_t *touchedicts[MAX_EDICTS];
991 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
994 chainfield = PRVM_G_INT(OFS_PARM2);
996 chainfield = prog->fieldoffsets.chain;
998 prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
1000 chain = (prvm_edict_t *)prog->edicts;
1002 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1003 radius = PRVM_G_FLOAT(OFS_PARM1);
1004 radius2 = radius * radius;
1006 mins[0] = org[0] - (radius + 1);
1007 mins[1] = org[1] - (radius + 1);
1008 mins[2] = org[2] - (radius + 1);
1009 maxs[0] = org[0] + (radius + 1);
1010 maxs[1] = org[1] + (radius + 1);
1011 maxs[2] = org[2] + (radius + 1);
1012 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1013 if (numtouchedicts > MAX_EDICTS)
1015 // this never happens
1016 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1017 numtouchedicts = MAX_EDICTS;
1019 for (i = 0;i < numtouchedicts;i++)
1021 ent = touchedicts[i];
1022 prog->xfunction->builtinsprofile++;
1023 // Quake did not return non-solid entities but darkplaces does
1024 // (note: this is the reason you can't blow up fallen zombies)
1025 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1027 // LordHavoc: compare against bounding box rather than center so it
1028 // doesn't miss large objects, and use DotProduct instead of Length
1029 // for a major speedup
1030 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1031 if (sv_gameplayfix_findradiusdistancetobox.integer)
1033 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1034 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1035 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1038 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1039 if (DotProduct(eorg, eorg) < radius2)
1041 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1046 VM_RETURN_EDICT(chain);
1049 static void VM_SV_precache_sound(prvm_prog_t *prog)
1051 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1052 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1055 static void VM_SV_precache_model(prvm_prog_t *prog)
1057 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1058 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1059 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1066 float(float yaw, float dist[, settrace]) walkmove
1069 static void VM_SV_walkmove(prvm_prog_t *prog)
1078 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1080 // assume failure if it returns early
1081 PRVM_G_FLOAT(OFS_RETURN) = 0;
1083 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1084 if (ent == prog->edicts)
1086 VM_Warning(prog, "walkmove: can not modify world entity\n");
1089 if (ent->priv.server->free)
1091 VM_Warning(prog, "walkmove: can not modify free entity\n");
1094 yaw = PRVM_G_FLOAT(OFS_PARM0);
1095 dist = PRVM_G_FLOAT(OFS_PARM1);
1096 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1098 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1101 yaw = yaw*M_PI*2 / 360;
1103 move[0] = cos(yaw)*dist;
1104 move[1] = sin(yaw)*dist;
1107 // save program state, because SV_movestep may call other progs
1108 oldf = prog->xfunction;
1109 oldself = PRVM_serverglobaledict(self);
1111 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1114 // restore program state
1115 prog->xfunction = oldf;
1116 PRVM_serverglobaledict(self) = oldself;
1127 static void VM_SV_droptofloor(prvm_prog_t *prog)
1130 vec3_t end, entorigin, entmins, entmaxs;
1133 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1135 // assume failure if it returns early
1136 PRVM_G_FLOAT(OFS_RETURN) = 0;
1138 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1139 if (ent == prog->edicts)
1141 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1144 if (ent->priv.server->free)
1146 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1150 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1153 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1154 if (sv_gameplayfix_unstickentities.integer)
1155 SV_UnstickEntity(ent);
1157 VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
1158 VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
1159 VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
1160 trace = SV_TraceBox(entorigin, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1161 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1164 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]);
1165 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1166 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1167 VectorSubtract(trace.endpos, offset, trace.endpos);
1168 if (trace.startsolid)
1170 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]);
1171 if (sv_gameplayfix_unstickentities.integer)
1172 SV_UnstickEntity(ent);
1174 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1175 PRVM_serveredictedict(ent, groundentity) = 0;
1176 PRVM_G_FLOAT(OFS_RETURN) = 1;
1178 else if (trace.fraction < 1)
1180 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]);
1181 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1182 if (sv_gameplayfix_unstickentities.integer)
1183 SV_UnstickEntity(ent);
1185 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1186 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1187 PRVM_G_FLOAT(OFS_RETURN) = 1;
1188 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1189 ent->priv.server->suspendedinairflag = true;
1194 if (trace.fraction != 1)
1196 if (trace.fraction < 1)
1197 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1199 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1200 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1201 PRVM_G_FLOAT(OFS_RETURN) = 1;
1202 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1203 ent->priv.server->suspendedinairflag = true;
1212 void(float style, string value) lightstyle
1215 static void VM_SV_lightstyle(prvm_prog_t *prog)
1222 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1224 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1225 val = PRVM_G_STRING(OFS_PARM1);
1227 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1228 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1231 // change the string in sv
1232 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1234 // send message to all clients on this server
1235 if (sv.state != ss_active)
1238 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1240 if (client->active && client->netconnection)
1242 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1243 MSG_WriteChar (&client->netconnection->message,style);
1244 MSG_WriteString (&client->netconnection->message, val);
1254 static void VM_SV_checkbottom(prvm_prog_t *prog)
1256 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1257 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1265 static void VM_SV_pointcontents(prvm_prog_t *prog)
1268 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1269 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point);
1270 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(point));
1277 Pick a vector for the player to shoot along
1278 vector aim(entity, missilespeed)
1281 static void VM_SV_aim(prvm_prog_t *prog)
1283 prvm_edict_t *ent, *check, *bestent;
1284 vec3_t start, dir, end, bestdir;
1287 float dist, bestdist;
1290 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1292 // assume failure if it returns early
1293 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1294 // if sv_aim is so high it can't possibly accept anything, skip out early
1295 if (sv_aim.value >= 1)
1298 ent = PRVM_G_EDICT(OFS_PARM0);
1299 if (ent == prog->edicts)
1301 VM_Warning(prog, "aim: can not use world entity\n");
1304 if (ent->priv.server->free)
1306 VM_Warning(prog, "aim: can not use free entity\n");
1309 //speed = PRVM_G_FLOAT(OFS_PARM1);
1311 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1314 // try sending a trace straight
1315 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1316 VectorMA (start, 2048, dir, end);
1317 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1318 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1319 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1321 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1326 // try all possible entities
1327 VectorCopy (dir, bestdir);
1328 bestdist = sv_aim.value;
1331 check = PRVM_NEXT_EDICT(prog->edicts);
1332 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1334 prog->xfunction->builtinsprofile++;
1335 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1339 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1340 continue; // don't aim at teammate
1341 for (j=0 ; j<3 ; j++)
1342 end[j] = PRVM_serveredictvector(check, origin)[j]
1343 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1344 VectorSubtract (end, start, dir);
1345 VectorNormalize (dir);
1346 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1347 if (dist < bestdist)
1348 continue; // to far to turn
1349 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1350 if (tr.ent == check)
1351 { // can shoot at this one
1359 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1360 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1361 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1363 VectorNormalize (end);
1364 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1368 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1373 ===============================================================================
1377 ===============================================================================
1380 #define MSG_BROADCAST 0 // unreliable to all
1381 #define MSG_ONE 1 // reliable to one (msg_entity)
1382 #define MSG_ALL 2 // reliable to all
1383 #define MSG_INIT 3 // write to the init string
1384 #define MSG_ENTITY 5
1386 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1392 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1396 return &sv.datagram;
1399 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1400 entnum = PRVM_NUM_FOR_EDICT(ent);
1401 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1403 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1404 return &sv.reliable_datagram;
1407 return &svs.clients[entnum-1].netconnection->message;
1410 VM_Warning(prog, "WriteDest: bad destination\n");
1412 return &sv.reliable_datagram;
1418 return sv.writeentitiestoclient_msg;
1424 static void VM_SV_WriteByte(prvm_prog_t *prog)
1426 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1427 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1430 static void VM_SV_WriteChar(prvm_prog_t *prog)
1432 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1433 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1436 static void VM_SV_WriteShort(prvm_prog_t *prog)
1438 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1439 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1442 static void VM_SV_WriteLong(prvm_prog_t *prog)
1444 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1445 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1448 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1450 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1451 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1454 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1456 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1457 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1460 static void VM_SV_WriteString(prvm_prog_t *prog)
1462 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1463 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1466 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1468 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1469 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1473 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1475 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1476 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1479 // writes a picture as at most size bytes of data
1481 // IMGNAME \0 SIZE(short) IMGDATA
1482 // if failed to read/compress:
1484 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1485 static void VM_SV_WritePicture(prvm_prog_t *prog)
1487 const char *imgname;
1491 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1493 imgname = PRVM_G_STRING(OFS_PARM1);
1494 size = (size_t) PRVM_G_FLOAT(OFS_PARM2);
1498 MSG_WriteString(WriteDest(prog), imgname);
1499 if(Image_Compress(imgname, size, &buf, &size))
1502 MSG_WriteShort(WriteDest(prog), size);
1503 SZ_Write(WriteDest(prog), (unsigned char *) buf, size);
1508 MSG_WriteShort(WriteDest(prog), 0);
1512 //////////////////////////////////////////////////////////
1514 static void VM_SV_makestatic(prvm_prog_t *prog)
1519 // allow 0 parameters due to an id1 qc bug in which this function is used
1520 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1521 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1523 if (prog->argc >= 1)
1524 ent = PRVM_G_EDICT(OFS_PARM0);
1526 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1527 if (ent == prog->edicts)
1529 VM_Warning(prog, "makestatic: can not modify world entity\n");
1532 if (ent->priv.server->free)
1534 VM_Warning(prog, "makestatic: can not modify free entity\n");
1539 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1544 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1545 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1546 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1548 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1550 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1551 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1552 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1556 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1557 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1558 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1561 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1562 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1563 for (i=0 ; i<3 ; i++)
1565 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1566 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1569 // throw the entity away now
1570 PRVM_ED_Free(prog, ent);
1573 //=============================================================================
1580 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1586 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1588 ent = PRVM_G_EDICT(OFS_PARM0);
1589 i = PRVM_NUM_FOR_EDICT(ent);
1590 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1592 Con_Print("tried to setspawnparms on a non-client\n");
1596 // copy spawn parms out of the client_t
1597 client = svs.clients + i-1;
1598 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1599 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1606 Returns a color vector indicating the lighting at the requested point.
1608 (Internal Operation note: actually measures the light beneath the point, just like
1609 the model lighting on the client)
1614 static void VM_SV_getlight(prvm_prog_t *prog)
1616 vec3_t ambientcolor, diffusecolor, diffusenormal;
1618 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1619 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
1620 VectorClear(ambientcolor);
1621 VectorClear(diffusecolor);
1622 VectorClear(diffusenormal);
1623 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1624 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1625 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1630 unsigned char type; // 1/2/8 or other value if isn't used
1634 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1635 static int vm_customstats_last;
1637 void VM_CustomStats_Clear (void)
1641 Z_Free(vm_customstats);
1642 vm_customstats = NULL;
1643 vm_customstats_last = -1;
1647 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1649 prvm_prog_t *prog = SVVM_prog;
1656 for(i=0; i<vm_customstats_last+1 ;i++)
1658 if(!vm_customstats[i].type)
1660 switch(vm_customstats[i].type)
1662 //string as 16 bytes
1665 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1666 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1667 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1668 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1669 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1671 //float field sent as-is
1673 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1675 //integer value of float field
1677 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1685 // void(float index, float type, .void field) SV_AddStat = #232;
1686 // Set up an auto-sent player stat.
1687 // Client's get thier own fields sent to them. Index may not be less than 32.
1688 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1689 // 1: string (4 stats carrying a total of 16 charactures)
1690 // 2: float (one stat, float converted to an integer for transportation)
1691 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1692 static void VM_SV_AddStat(prvm_prog_t *prog)
1697 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1701 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1704 VM_Warning(prog, "PF_SV_AddStat: not enough memory\n");
1708 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1709 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1710 off = PRVM_G_INT (OFS_PARM2);
1715 VM_Warning(prog, "PF_SV_AddStat: index may not be less than 32\n");
1718 if(i >= (MAX_CL_STATS-32))
1720 VM_Warning(prog, "PF_SV_AddStat: index >= MAX_CL_STATS\n");
1723 if(i > (MAX_CL_STATS-32-4) && type == 1)
1725 VM_Warning(prog, "PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1728 vm_customstats[i].type = type;
1729 vm_customstats[i].fieldoffset = off;
1730 if(vm_customstats_last < i)
1731 vm_customstats_last = i;
1738 copies data from one entity to another
1740 copyentity(src, dst)
1743 static void VM_SV_copyentity(prvm_prog_t *prog)
1745 prvm_edict_t *in, *out;
1746 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1747 in = PRVM_G_EDICT(OFS_PARM0);
1748 if (in == prog->edicts)
1750 VM_Warning(prog, "copyentity: can not read world entity\n");
1753 if (in->priv.server->free)
1755 VM_Warning(prog, "copyentity: can not read free entity\n");
1758 out = PRVM_G_EDICT(OFS_PARM1);
1759 if (out == prog->edicts)
1761 VM_Warning(prog, "copyentity: can not modify world entity\n");
1764 if (out->priv.server->free)
1766 VM_Warning(prog, "copyentity: can not modify free entity\n");
1769 memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
1778 sets the color of a client and broadcasts the update to all connected clients
1780 setcolor(clientent, value)
1783 static void VM_SV_setcolor(prvm_prog_t *prog)
1788 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1789 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1790 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1792 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1794 Con_Print("tried to setcolor a non-client\n");
1798 client = svs.clients + entnum-1;
1801 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1802 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1805 if (client->old_colors != client->colors)
1807 client->old_colors = client->colors;
1808 // send notification to all clients
1809 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1810 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1811 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1819 effect(origin, modelname, startframe, framecount, framerate)
1822 static void VM_SV_effect(prvm_prog_t *prog)
1827 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1828 s = PRVM_G_STRING(OFS_PARM1);
1831 VM_Warning(prog, "effect: no model specified\n");
1835 i = SV_ModelIndex(s, 1);
1838 VM_Warning(prog, "effect: model not precached\n");
1842 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1844 VM_Warning(prog, "effect: framecount < 1\n");
1848 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1850 VM_Warning(prog, "effect: framerate < 1\n");
1854 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1855 SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1858 static void VM_SV_te_blood(prvm_prog_t *prog)
1860 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1861 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1863 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1864 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1866 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1868 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1870 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1871 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1872 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1874 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1875 SV_FlushBroadcastMessages();
1878 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1880 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1881 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1883 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1884 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1886 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1887 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1888 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1890 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1891 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1892 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1894 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1896 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1897 SV_FlushBroadcastMessages();
1900 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1902 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1903 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1904 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1910 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1911 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1912 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1913 SV_FlushBroadcastMessages();
1916 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1918 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1919 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1921 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1922 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1924 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1925 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1926 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1934 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1936 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1938 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1939 // gravity true/false
1940 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1942 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1943 SV_FlushBroadcastMessages();
1946 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1948 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1949 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1951 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1952 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1954 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1955 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1964 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1966 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1968 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1969 SV_FlushBroadcastMessages();
1972 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1974 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1975 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1977 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1978 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1980 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1984 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1985 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1989 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1990 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1992 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1994 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1995 SV_FlushBroadcastMessages();
1998 static void VM_SV_te_spark(prvm_prog_t *prog)
2000 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
2001 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2003 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2004 MSG_WriteByte(&sv.datagram, TE_SPARK);
2006 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2007 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2008 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2010 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2011 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2012 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2014 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2015 SV_FlushBroadcastMessages();
2018 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2020 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2021 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2022 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2024 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2025 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2026 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2027 SV_FlushBroadcastMessages();
2030 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2032 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2033 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2034 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2036 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2037 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2038 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2039 SV_FlushBroadcastMessages();
2042 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2044 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2045 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2046 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2048 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2049 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2050 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2051 SV_FlushBroadcastMessages();
2054 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2056 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2057 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2058 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2060 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2061 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2062 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2063 SV_FlushBroadcastMessages();
2066 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2068 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2069 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2070 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2072 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2074 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2075 SV_FlushBroadcastMessages();
2078 static void VM_SV_te_customflash(prvm_prog_t *prog)
2080 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2081 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2083 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2084 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2086 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2087 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2088 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2090 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2092 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2094 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2095 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2096 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2097 SV_FlushBroadcastMessages();
2100 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2102 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2103 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2104 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2106 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2107 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2108 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2109 SV_FlushBroadcastMessages();
2112 static void VM_SV_te_spike(prvm_prog_t *prog)
2114 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2115 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2116 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2118 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2119 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2120 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2121 SV_FlushBroadcastMessages();
2124 static void VM_SV_te_superspike(prvm_prog_t *prog)
2126 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2127 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2128 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2130 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2131 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2132 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2133 SV_FlushBroadcastMessages();
2136 static void VM_SV_te_explosion(prvm_prog_t *prog)
2138 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2139 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2140 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2142 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2143 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2144 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2145 SV_FlushBroadcastMessages();
2148 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2150 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2151 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2152 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2154 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2155 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2156 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2157 SV_FlushBroadcastMessages();
2160 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2162 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2163 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2164 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2166 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2167 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2168 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2169 SV_FlushBroadcastMessages();
2172 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2174 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2175 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2176 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2178 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2179 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2180 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2181 SV_FlushBroadcastMessages();
2184 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2186 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2187 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2188 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2190 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2191 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2192 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2193 SV_FlushBroadcastMessages();
2196 static void VM_SV_te_teleport(prvm_prog_t *prog)
2198 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2199 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2200 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2202 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2203 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2204 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2205 SV_FlushBroadcastMessages();
2208 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2210 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2211 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2212 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2214 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2215 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2216 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2218 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2219 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2220 SV_FlushBroadcastMessages();
2223 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2225 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2226 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2227 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2229 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2231 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2232 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2235 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2236 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2237 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2238 SV_FlushBroadcastMessages();
2241 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2243 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2244 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2245 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2247 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2249 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2250 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2251 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2253 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2254 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2255 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2256 SV_FlushBroadcastMessages();
2259 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2261 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2262 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2263 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2265 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2267 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2268 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2269 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2271 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2272 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2273 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2274 SV_FlushBroadcastMessages();
2277 static void VM_SV_te_beam(prvm_prog_t *prog)
2279 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2280 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2281 MSG_WriteByte(&sv.datagram, TE_BEAM);
2283 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2285 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2286 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2287 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2289 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2290 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2291 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2292 SV_FlushBroadcastMessages();
2295 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2297 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2298 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2299 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2300 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2301 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2302 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2303 SV_FlushBroadcastMessages();
2306 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2308 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2309 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2310 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2312 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2313 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2314 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2316 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2317 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2318 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2320 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2321 SV_FlushBroadcastMessages();
2324 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2325 //this function originally written by KrimZon, made shorter by LordHavoc
2326 static void VM_SV_clientcommand(prvm_prog_t *prog)
2328 client_t *temp_client;
2330 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2332 //find client for this entity
2333 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2334 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2336 Con_Print("PF_clientcommand: entity is not a client\n");
2340 temp_client = host_client;
2341 host_client = svs.clients + i;
2342 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
2343 host_client = temp_client;
2346 //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)
2347 static void VM_SV_setattachment(prvm_prog_t *prog)
2349 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2350 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2351 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2354 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2356 if (e == prog->edicts)
2358 VM_Warning(prog, "setattachment: can not modify world entity\n");
2361 if (e->priv.server->free)
2363 VM_Warning(prog, "setattachment: can not modify free entity\n");
2367 if (tagentity == NULL)
2368 tagentity = prog->edicts;
2372 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2374 model = SV_GetModelFromEdict(tagentity);
2377 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2379 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);
2382 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));
2385 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2386 PRVM_serveredictfloat(e, tag_index) = tagindex;
2389 /////////////////////////////////////////
2390 // DP_MD3_TAGINFO extension coded by VorteX
2392 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2396 i = (int)PRVM_serveredictfloat(e, modelindex);
2397 if (i < 1 || i >= MAX_MODELS)
2400 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2403 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2410 Matrix4x4_CreateIdentity(tag_localmatrix);
2412 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2414 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2425 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2428 float pitchsign = 1;
2430 scale = PRVM_serveredictfloat(ent, scale);
2435 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);
2438 pitchsign = SV_GetPitchSign(prog, ent);
2439 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);
2443 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2446 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2448 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2449 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2450 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2451 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2453 *out = identitymatrix;
2457 // Warnings/errors code:
2458 // 0 - normal (everything all-right)
2461 // 3 - null or non-precached model
2462 // 4 - no tags with requested index
2463 // 5 - runaway loop at attachment chain
2464 extern cvar_t cl_bob;
2465 extern cvar_t cl_bobcycle;
2466 extern cvar_t cl_bobup;
2467 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2470 int modelindex, attachloop;
2471 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2474 *out = identitymatrix; // warnings and errors return identical matrix
2476 if (ent == prog->edicts)
2478 if (ent->priv.server->free)
2481 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2482 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2485 model = SV_GetModelByIndex(modelindex);
2487 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2488 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2489 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2491 tagmatrix = identitymatrix;
2492 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2496 if (attachloop >= 256) // prevent runaway looping
2498 // apply transformation by child's tagindex on parent entity and then
2499 // by parent entity itself
2500 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2501 if (ret && attachloop == 0)
2503 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2504 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2505 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2506 // next iteration we process the parent entity
2507 if (PRVM_serveredictedict(ent, tag_entity))
2509 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2510 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2517 // RENDER_VIEWMODEL magic
2518 if (PRVM_serveredictedict(ent, viewmodelforclient))
2520 Matrix4x4_Copy(&tagmatrix, out);
2521 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2523 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2524 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2527 // Cl_bob, ported from rendering code
2528 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2531 // LordHavoc: this code is *weird*, but not replacable (I think it
2532 // should be done in QC on the server, but oh well, quake is quake)
2533 // LordHavoc: figured out bobup: the time at which the sin is at 180
2534 // degrees (which allows lengthening or squishing the peak or valley)
2535 cycle = sv.time/cl_bobcycle.value;
2536 cycle -= (int)cycle;
2537 if (cycle < cl_bobup.value)
2538 cycle = sin(M_PI * cycle / cl_bobup.value);
2540 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2541 // bob is proportional to velocity in the xy plane
2542 // (don't count Z, or jumping messes it up)
2543 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;
2544 bob = bob*0.3 + bob*0.7*cycle;
2545 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2552 //float(entity ent, string tagname) gettagindex;
2554 static void VM_SV_gettagindex(prvm_prog_t *prog)
2557 const char *tag_name;
2560 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2562 ent = PRVM_G_EDICT(OFS_PARM0);
2563 tag_name = PRVM_G_STRING(OFS_PARM1);
2565 if (ent == prog->edicts)
2567 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2570 if (ent->priv.server->free)
2572 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2577 if (!SV_GetModelFromEdict(ent))
2578 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2581 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2583 if(developer_extra.integer)
2584 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2586 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2589 //vector(entity ent, float tagindex) gettaginfo;
2590 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2594 matrix4x4_t tag_matrix;
2595 matrix4x4_t tag_localmatrix;
2597 const char *tagname;
2599 vec3_t forward, left, up, origin;
2600 const dp_model_t *model;
2602 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2604 e = PRVM_G_EDICT(OFS_PARM0);
2605 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2607 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2608 Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
2609 VectorCopy(forward, PRVM_serverglobalvector(v_forward));
2610 VectorNegate(left, PRVM_serverglobalvector(v_right));
2611 VectorCopy(up, PRVM_serverglobalvector(v_up));
2612 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2613 model = SV_GetModelFromEdict(e);
2614 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2615 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2616 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2617 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2618 Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
2620 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2621 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2622 VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
2623 VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
2624 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2625 VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset));
2630 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2633 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2636 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2639 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2642 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2647 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2648 static void VM_SV_dropclient(prvm_prog_t *prog)
2651 client_t *oldhostclient;
2652 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2653 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2654 if (clientnum < 0 || clientnum >= svs.maxclients)
2656 VM_Warning(prog, "dropclient: not a client\n");
2659 if (!svs.clients[clientnum].active)
2661 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2664 oldhostclient = host_client;
2665 host_client = svs.clients + clientnum;
2666 SV_DropClient(false);
2667 host_client = oldhostclient;
2670 //entity() spawnclient (DP_SV_BOTCLIENT)
2671 static void VM_SV_spawnclient(prvm_prog_t *prog)
2675 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2676 prog->xfunction->builtinsprofile += 2;
2678 for (i = 0;i < svs.maxclients;i++)
2680 if (!svs.clients[i].active)
2682 prog->xfunction->builtinsprofile += 100;
2683 SV_ConnectClient (i, NULL);
2684 // this has to be set or else ClientDisconnect won't be called
2685 // we assume the qc will call ClientConnect...
2686 svs.clients[i].clientconnectcalled = true;
2687 ed = PRVM_EDICT_NUM(i + 1);
2691 VM_RETURN_EDICT(ed);
2694 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2695 static void VM_SV_clienttype(prvm_prog_t *prog)
2698 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2699 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2700 if (clientnum < 0 || clientnum >= svs.maxclients)
2701 PRVM_G_FLOAT(OFS_RETURN) = 3;
2702 else if (!svs.clients[clientnum].active)
2703 PRVM_G_FLOAT(OFS_RETURN) = 0;
2704 else if (svs.clients[clientnum].netconnection)
2705 PRVM_G_FLOAT(OFS_RETURN) = 1;
2707 PRVM_G_FLOAT(OFS_RETURN) = 2;
2714 string(string key) serverkey
2717 static void VM_SV_serverkey(prvm_prog_t *prog)
2719 char string[VM_STRINGTEMP_LENGTH];
2720 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2721 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2722 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2725 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2726 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2731 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2733 e = PRVM_G_EDICT(OFS_PARM0);
2734 if (e == prog->edicts)
2736 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2739 if (e->priv.server->free)
2741 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2744 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2745 if (i <= 0 || i >= MAX_MODELS)
2747 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2750 if (!sv.model_precache[i][0])
2752 VM_Warning(prog, "setmodelindex: model not precached\n");
2756 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2757 PRVM_serveredictfloat(e, modelindex) = i;
2759 mod = SV_GetModelByIndex(i);
2763 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2764 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2766 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2769 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2772 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2773 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2776 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2778 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2780 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2781 if (i <= 0 || i >= MAX_MODELS)
2783 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2786 if (!sv.model_precache[i][0])
2788 VM_Warning(prog, "modelnameforindex: model not precached\n");
2792 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2795 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2796 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2799 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2800 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2803 PRVM_G_FLOAT(OFS_RETURN) = i;
2806 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2807 static void VM_SV_trailparticles(prvm_prog_t *prog)
2810 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2812 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2815 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2816 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2817 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2818 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start);
2819 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end);
2820 MSG_WriteVector(&sv.datagram, start, sv.protocol);
2821 MSG_WriteVector(&sv.datagram, end, sv.protocol);
2822 SV_FlushBroadcastMessages();
2825 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2826 static void VM_SV_pointparticles(prvm_prog_t *prog)
2828 int effectnum, count;
2830 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2832 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2835 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2836 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2837 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2838 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2839 if (count == 1 && !VectorLength2(vel))
2842 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2843 MSG_WriteShort(&sv.datagram, effectnum);
2844 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2848 // 1+2+12+12+2=29 bytes
2849 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2850 MSG_WriteShort(&sv.datagram, effectnum);
2851 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2852 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2853 MSG_WriteShort(&sv.datagram, count);
2856 SV_FlushBroadcastMessages();
2859 //PF_setpause, // void(float pause) setpause = #531;
2860 static void VM_SV_setpause(prvm_prog_t *prog) {
2862 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2863 if (pauseValue != 0) { //pause the game
2865 sv.pausedstart = realtime;
2866 } else { //disable pause, in case it was enabled
2867 if (sv.paused != 0) {
2872 // send notification to all clients
2873 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2874 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2877 // #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.
2878 static void VM_SV_skel_create(prvm_prog_t *prog)
2880 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2881 dp_model_t *model = SV_GetModelByIndex(modelindex);
2882 skeleton_t *skeleton;
2884 PRVM_G_FLOAT(OFS_RETURN) = 0;
2885 if (!model || !model->num_bones)
2887 for (i = 0;i < MAX_EDICTS;i++)
2888 if (!prog->skeletons[i])
2890 if (i == MAX_EDICTS)
2892 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(prog->progs_mempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2893 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2894 skeleton->model = model;
2895 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2896 // initialize to identity matrices
2897 for (i = 0;i < skeleton->model->num_bones;i++)
2898 skeleton->relativetransforms[i] = identitymatrix;
2901 // #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
2902 static void VM_SV_skel_build(prvm_prog_t *prog)
2904 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2905 skeleton_t *skeleton;
2906 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2907 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2908 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2909 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2910 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2911 dp_model_t *model = SV_GetModelByIndex(modelindex);
2915 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2916 frameblend_t frameblend[MAX_FRAMEBLENDS];
2917 matrix4x4_t bonematrix;
2919 PRVM_G_FLOAT(OFS_RETURN) = 0;
2920 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2922 firstbone = max(0, firstbone);
2923 lastbone = min(lastbone, model->num_bones - 1);
2924 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2925 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2926 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time);
2927 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2929 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2931 memset(&bonematrix, 0, sizeof(bonematrix));
2932 for (blendindex = 0;blendindex < numblends;blendindex++)
2934 Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2935 Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp);
2937 Matrix4x4_Normalize3(&bonematrix, &bonematrix);
2938 Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac);
2940 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2943 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2944 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
2946 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2947 skeleton_t *skeleton;
2948 PRVM_G_FLOAT(OFS_RETURN) = 0;
2949 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2951 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2954 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2955 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
2957 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2958 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2959 skeleton_t *skeleton;
2960 PRVM_G_INT(OFS_RETURN) = 0;
2961 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2963 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2965 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
2968 // #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)
2969 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
2971 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2972 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2973 skeleton_t *skeleton;
2974 PRVM_G_FLOAT(OFS_RETURN) = 0;
2975 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2977 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2979 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2982 // #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
2983 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
2985 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2986 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2987 skeleton_t *skeleton;
2988 PRVM_G_FLOAT(OFS_RETURN) = 0;
2989 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2991 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2994 // #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)
2995 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
2997 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2998 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2999 skeleton_t *skeleton;
3001 vec3_t forward, left, up, origin;
3002 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3003 VectorClear(PRVM_clientglobalvector(v_forward));
3004 VectorClear(PRVM_clientglobalvector(v_right));
3005 VectorClear(PRVM_clientglobalvector(v_up));
3006 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3008 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3010 matrix = skeleton->relativetransforms[bonenum];
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 // #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)
3019 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
3021 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3022 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3023 skeleton_t *skeleton;
3026 vec3_t forward, left, up, origin;
3027 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3028 VectorClear(PRVM_clientglobalvector(v_forward));
3029 VectorClear(PRVM_clientglobalvector(v_right));
3030 VectorClear(PRVM_clientglobalvector(v_up));
3031 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3033 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3035 matrix = skeleton->relativetransforms[bonenum];
3036 // convert to absolute
3037 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3040 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3042 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3043 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3044 VectorNegate(left, PRVM_clientglobalvector(v_right));
3045 VectorCopy(up, PRVM_clientglobalvector(v_up));
3046 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3049 // #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)
3050 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3052 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3053 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3054 vec3_t forward, left, up, origin;
3055 skeleton_t *skeleton;
3057 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3059 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3061 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3062 VectorNegate(PRVM_clientglobalvector(v_right), left);
3063 VectorCopy(PRVM_clientglobalvector(v_up), up);
3064 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3065 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3066 skeleton->relativetransforms[bonenum] = matrix;
3069 // #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)
3070 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3072 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3073 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3074 vec3_t forward, left, up, origin;
3075 skeleton_t *skeleton;
3078 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3080 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3082 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3083 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3084 VectorNegate(PRVM_clientglobalvector(v_right), left);
3085 VectorCopy(PRVM_clientglobalvector(v_up), up);
3086 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3087 temp = skeleton->relativetransforms[bonenum];
3088 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3091 // #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)
3092 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3094 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3095 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3096 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3098 vec3_t forward, left, up, origin;
3099 skeleton_t *skeleton;
3102 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3104 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3105 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3106 VectorNegate(PRVM_clientglobalvector(v_right), left);
3107 VectorCopy(PRVM_clientglobalvector(v_up), up);
3108 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3109 firstbone = max(0, firstbone);
3110 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3111 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3113 temp = skeleton->relativetransforms[bonenum];
3114 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3118 // #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
3119 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3121 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3122 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3123 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3124 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3126 skeleton_t *skeletondst;
3127 skeleton_t *skeletonsrc;
3128 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3130 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3132 firstbone = max(0, firstbone);
3133 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3134 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3135 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3136 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3139 // #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)
3140 static void VM_SV_skel_delete(prvm_prog_t *prog)
3142 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3143 skeleton_t *skeleton;
3144 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3147 prog->skeletons[skeletonindex] = NULL;
3150 // #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
3151 static void VM_SV_frameforname(prvm_prog_t *prog)
3153 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3154 dp_model_t *model = SV_GetModelByIndex(modelindex);
3155 const char *name = PRVM_G_STRING(OFS_PARM1);
3157 PRVM_G_FLOAT(OFS_RETURN) = -1;
3158 if (!model || !model->animscenes)
3160 for (i = 0;i < model->numframes;i++)
3162 if (!strcasecmp(model->animscenes[i].name, name))
3164 PRVM_G_FLOAT(OFS_RETURN) = i;
3170 // #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.
3171 static void VM_SV_frameduration(prvm_prog_t *prog)
3173 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3174 dp_model_t *model = SV_GetModelByIndex(modelindex);
3175 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3176 PRVM_G_FLOAT(OFS_RETURN) = 0;
3177 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3179 if (model->animscenes[framenum].framerate)
3180 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3184 prvm_builtin_t vm_sv_builtins[] = {
3185 NULL, // #0 NULL function (not callable) (QUAKE)
3186 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3187 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3188 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3189 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3190 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3191 VM_break, // #6 void() break (QUAKE)
3192 VM_random, // #7 float() random (QUAKE)
3193 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3194 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3195 VM_error, // #10 void(string e) error (QUAKE)
3196 VM_objerror, // #11 void(string e) objerror (QUAKE)
3197 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3198 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3199 VM_spawn, // #14 entity() spawn (QUAKE)
3200 VM_remove, // #15 void(entity e) remove (QUAKE)
3201 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3202 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3203 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3204 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3205 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3206 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3207 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3208 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3209 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3210 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3211 VM_ftos, // #26 string(float f) ftos (QUAKE)
3212 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3213 VM_coredump, // #28 void() coredump (QUAKE)
3214 VM_traceon, // #29 void() traceon (QUAKE)
3215 VM_traceoff, // #30 void() traceoff (QUAKE)
3216 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3217 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3218 NULL, // #33 (QUAKE)
3219 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3220 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3221 VM_rint, // #36 float(float v) rint (QUAKE)
3222 VM_floor, // #37 float(float v) floor (QUAKE)
3223 VM_ceil, // #38 float(float v) ceil (QUAKE)
3224 NULL, // #39 (QUAKE)
3225 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3226 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3227 NULL, // #42 (QUAKE)
3228 VM_fabs, // #43 float(float f) fabs (QUAKE)
3229 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3230 VM_cvar, // #45 float(string s) cvar (QUAKE)
3231 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3232 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3233 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3234 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3235 NULL, // #50 (QUAKE)
3236 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3237 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3238 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3239 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3240 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3241 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3242 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3243 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3244 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3245 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3246 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3247 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3248 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3249 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3250 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3251 NULL, // #66 (QUAKE)
3252 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3253 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3254 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3255 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3256 NULL, // #71 (QUAKE)
3257 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3258 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3259 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3260 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3261 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3262 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3263 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3264 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3265 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3266 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3267 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3268 NULL, // #83 (QUAKE)
3269 NULL, // #84 (QUAKE)
3270 NULL, // #85 (QUAKE)
3271 NULL, // #86 (QUAKE)
3272 NULL, // #87 (QUAKE)
3273 NULL, // #88 (QUAKE)
3274 NULL, // #89 (QUAKE)
3275 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3276 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3277 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3278 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3279 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3280 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3281 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3282 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3283 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3284 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3285 // FrikaC and Telejano range #100-#199
3296 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3297 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3298 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3299 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3300 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3301 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3302 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3303 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3304 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3305 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3386 // FTEQW range #200-#299
3405 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3408 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3409 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3410 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3411 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3412 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3413 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3414 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3415 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3416 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3417 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3419 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3427 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3450 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.
3451 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
3452 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3453 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3454 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)
3455 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
3456 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)
3457 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)
3458 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)
3459 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)
3460 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)
3461 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
3462 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)
3463 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
3464 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.
3487 // CSQC range #300-#399
3488 NULL, // #300 void() clearscene (EXT_CSQC)
3489 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3490 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3491 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3492 NULL, // #304 void() renderscene (EXT_CSQC)
3493 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3494 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3495 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3496 NULL, // #308 void() R_EndPolygon
3498 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3499 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3503 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3504 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3505 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3506 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3507 NULL, // #319 void(string name) freepic (EXT_CSQC)
3508 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3509 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3510 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3511 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3512 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3513 NULL, // #325 void(void) drawresetcliparea
3518 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3519 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3520 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3521 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3522 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3523 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3524 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3525 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3526 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3527 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3528 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3529 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3530 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3531 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3532 NULL, // #344 vector() getmousepos (EXT_CSQC)
3533 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3534 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3535 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3536 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3537 NULL, // #349 float() isdemo (EXT_CSQC)
3538 VM_isserver, // #350 float() isserver (EXT_CSQC)
3539 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3540 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3541 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3542 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3548 NULL, // #360 float() readbyte (EXT_CSQC)
3549 NULL, // #361 float() readchar (EXT_CSQC)
3550 NULL, // #362 float() readshort (EXT_CSQC)
3551 NULL, // #363 float() readlong (EXT_CSQC)
3552 NULL, // #364 float() readcoord (EXT_CSQC)
3553 NULL, // #365 float() readangle (EXT_CSQC)
3554 NULL, // #366 string() readstring (EXT_CSQC)
3555 NULL, // #367 float() readfloat (EXT_CSQC)
3588 // LordHavoc's range #400-#499
3589 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3590 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3591 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3592 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3593 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3594 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3595 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3596 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3597 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)
3598 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3599 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3600 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3601 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3602 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3603 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3604 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3605 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3606 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3607 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3608 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3609 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3610 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3611 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3612 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3613 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3614 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3615 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3616 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3617 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3618 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3619 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3620 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3621 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3622 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3623 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3624 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3625 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3626 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3627 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3628 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3629 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3630 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3631 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3632 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3633 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3634 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3635 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3636 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3637 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3638 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3639 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3640 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3641 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3642 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3643 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3644 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3645 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3646 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3648 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3649 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3650 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3651 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3652 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3653 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3654 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3655 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3656 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3657 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3658 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3660 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3661 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3662 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3663 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3664 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3665 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3666 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3667 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3668 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3669 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3670 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3671 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3672 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3673 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3674 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3675 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3683 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3684 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3685 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3686 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3687 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3688 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3689 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3690 VM_SV_WritePicture, // #501
3692 VM_whichpack, // #503 string(string) whichpack = #503;
3699 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3700 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3701 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3702 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)
3703 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3704 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3705 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3706 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3707 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3708 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3718 VM_loadfromdata, // #529
3719 VM_loadfromfile, // #530
3720 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3722 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3723 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3724 VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP)
3725 VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP)
3726 VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP)
3727 VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP)
3729 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3730 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3731 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3794 VM_callfunction, // #605
3795 VM_writetofile, // #606
3796 VM_isfunction, // #607
3802 VM_parseentitydata, // #613
3813 VM_SV_getextresponse, // #624 string getextresponse(void)
3816 VM_sprintf, // #627 string sprintf(string format, ...)
3817 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3818 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3828 VM_digest_hex, // #639
3832 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3834 void SVVM_init_cmd(prvm_prog_t *prog)
3839 void SVVM_reset_cmd(prvm_prog_t *prog)
3841 World_End(&sv.world);
3842 if(PRVM_serverfunction(SV_Shutdown))
3844 func_t s = PRVM_serverfunction(SV_Shutdown);
3845 PRVM_serverglobalfloat(time) = sv.time;
3846 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3847 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");