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 SV_NudgeOutOfSolid(ent);
1156 VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
1157 VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
1158 VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
1159 trace = SV_TraceBox(entorigin, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1160 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1163 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]);
1164 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1165 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1166 VectorSubtract(trace.endpos, offset, trace.endpos);
1167 if (trace.startsolid)
1169 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 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1172 PRVM_serveredictedict(ent, groundentity) = 0;
1173 PRVM_G_FLOAT(OFS_RETURN) = 1;
1175 else if (trace.fraction < 1)
1177 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]);
1178 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1179 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1180 SV_NudgeOutOfSolid(ent);
1182 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1183 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1184 PRVM_G_FLOAT(OFS_RETURN) = 1;
1185 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1186 ent->priv.server->suspendedinairflag = true;
1191 if (!trace.allsolid && trace.fraction < 1)
1193 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1195 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1196 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1197 PRVM_G_FLOAT(OFS_RETURN) = 1;
1198 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1199 ent->priv.server->suspendedinairflag = true;
1208 void(float style, string value) lightstyle
1211 static void VM_SV_lightstyle(prvm_prog_t *prog)
1218 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1220 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1221 val = PRVM_G_STRING(OFS_PARM1);
1223 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1224 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1227 // change the string in sv
1228 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1230 // send message to all clients on this server
1231 if (sv.state != ss_active)
1234 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1236 if (client->active && client->netconnection)
1238 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1239 MSG_WriteChar (&client->netconnection->message,style);
1240 MSG_WriteString (&client->netconnection->message, val);
1250 static void VM_SV_checkbottom(prvm_prog_t *prog)
1252 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1253 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1261 static void VM_SV_pointcontents(prvm_prog_t *prog)
1264 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1265 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point);
1266 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(point));
1273 Pick a vector for the player to shoot along
1274 vector aim(entity, missilespeed)
1277 static void VM_SV_aim(prvm_prog_t *prog)
1279 prvm_edict_t *ent, *check, *bestent;
1280 vec3_t start, dir, end, bestdir;
1283 float dist, bestdist;
1286 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1288 // assume failure if it returns early
1289 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1290 // if sv_aim is so high it can't possibly accept anything, skip out early
1291 if (sv_aim.value >= 1)
1294 ent = PRVM_G_EDICT(OFS_PARM0);
1295 if (ent == prog->edicts)
1297 VM_Warning(prog, "aim: can not use world entity\n");
1300 if (ent->priv.server->free)
1302 VM_Warning(prog, "aim: can not use free entity\n");
1305 //speed = PRVM_G_FLOAT(OFS_PARM1);
1307 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1310 // try sending a trace straight
1311 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1312 VectorMA (start, 2048, dir, end);
1313 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1314 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1315 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1317 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1322 // try all possible entities
1323 VectorCopy (dir, bestdir);
1324 bestdist = sv_aim.value;
1327 check = PRVM_NEXT_EDICT(prog->edicts);
1328 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1330 prog->xfunction->builtinsprofile++;
1331 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1335 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1336 continue; // don't aim at teammate
1337 for (j=0 ; j<3 ; j++)
1338 end[j] = PRVM_serveredictvector(check, origin)[j]
1339 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1340 VectorSubtract (end, start, dir);
1341 VectorNormalize (dir);
1342 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1343 if (dist < bestdist)
1344 continue; // to far to turn
1345 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1346 if (tr.ent == check)
1347 { // can shoot at this one
1355 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1356 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1357 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1359 VectorNormalize (end);
1360 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1364 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1369 ===============================================================================
1373 ===============================================================================
1376 #define MSG_BROADCAST 0 // unreliable to all
1377 #define MSG_ONE 1 // reliable to one (msg_entity)
1378 #define MSG_ALL 2 // reliable to all
1379 #define MSG_INIT 3 // write to the init string
1380 #define MSG_ENTITY 5
1382 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1388 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1392 return &sv.datagram;
1395 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1396 entnum = PRVM_NUM_FOR_EDICT(ent);
1397 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1399 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1400 return &sv.reliable_datagram;
1403 return &svs.clients[entnum-1].netconnection->message;
1406 VM_Warning(prog, "WriteDest: bad destination\n");
1408 return &sv.reliable_datagram;
1414 return sv.writeentitiestoclient_msg;
1420 static void VM_SV_WriteByte(prvm_prog_t *prog)
1422 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1423 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1426 static void VM_SV_WriteChar(prvm_prog_t *prog)
1428 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1429 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1432 static void VM_SV_WriteShort(prvm_prog_t *prog)
1434 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1435 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1438 static void VM_SV_WriteLong(prvm_prog_t *prog)
1440 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1441 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1444 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1446 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1447 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1450 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1452 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1453 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1456 static void VM_SV_WriteString(prvm_prog_t *prog)
1458 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1459 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1462 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1464 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1465 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1469 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1471 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1472 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1475 // writes a picture as at most size bytes of data
1477 // IMGNAME \0 SIZE(short) IMGDATA
1478 // if failed to read/compress:
1480 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1481 static void VM_SV_WritePicture(prvm_prog_t *prog)
1483 const char *imgname;
1487 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1489 imgname = PRVM_G_STRING(OFS_PARM1);
1490 size = (size_t) PRVM_G_FLOAT(OFS_PARM2);
1494 MSG_WriteString(WriteDest(prog), imgname);
1495 if(Image_Compress(imgname, size, &buf, &size))
1498 MSG_WriteShort(WriteDest(prog), size);
1499 SZ_Write(WriteDest(prog), (unsigned char *) buf, size);
1504 MSG_WriteShort(WriteDest(prog), 0);
1508 //////////////////////////////////////////////////////////
1510 static void VM_SV_makestatic(prvm_prog_t *prog)
1515 // allow 0 parameters due to an id1 qc bug in which this function is used
1516 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1517 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1519 if (prog->argc >= 1)
1520 ent = PRVM_G_EDICT(OFS_PARM0);
1522 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1523 if (ent == prog->edicts)
1525 VM_Warning(prog, "makestatic: can not modify world entity\n");
1528 if (ent->priv.server->free)
1530 VM_Warning(prog, "makestatic: can not modify free entity\n");
1535 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1540 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1541 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1542 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1544 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1546 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1547 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1548 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1552 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1553 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1554 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1557 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1558 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1559 for (i=0 ; i<3 ; i++)
1561 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1562 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1565 // throw the entity away now
1566 PRVM_ED_Free(prog, ent);
1569 //=============================================================================
1576 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1582 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1584 ent = PRVM_G_EDICT(OFS_PARM0);
1585 i = PRVM_NUM_FOR_EDICT(ent);
1586 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1588 Con_Print("tried to setspawnparms on a non-client\n");
1592 // copy spawn parms out of the client_t
1593 client = svs.clients + i-1;
1594 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1595 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1602 Returns a color vector indicating the lighting at the requested point.
1604 (Internal Operation note: actually measures the light beneath the point, just like
1605 the model lighting on the client)
1610 static void VM_SV_getlight(prvm_prog_t *prog)
1612 vec3_t ambientcolor, diffusecolor, diffusenormal;
1614 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1615 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
1616 VectorClear(ambientcolor);
1617 VectorClear(diffusecolor);
1618 VectorClear(diffusenormal);
1619 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1620 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1621 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1626 unsigned char type; // 1/2/8 or other value if isn't used
1630 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1631 static int vm_customstats_last;
1633 void VM_CustomStats_Clear (void)
1637 Z_Free(vm_customstats);
1638 vm_customstats = NULL;
1639 vm_customstats_last = -1;
1643 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1645 prvm_prog_t *prog = SVVM_prog;
1652 for(i=0; i<vm_customstats_last+1 ;i++)
1654 if(!vm_customstats[i].type)
1656 switch(vm_customstats[i].type)
1658 //string as 16 bytes
1661 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1662 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1663 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1664 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1665 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1667 //float field sent as-is
1669 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1671 //integer value of float field
1673 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1681 // void(float index, float type, .void field) SV_AddStat = #232;
1682 // Set up an auto-sent player stat.
1683 // Client's get thier own fields sent to them. Index may not be less than 32.
1684 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1685 // 1: string (4 stats carrying a total of 16 charactures)
1686 // 2: float (one stat, float converted to an integer for transportation)
1687 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1688 static void VM_SV_AddStat(prvm_prog_t *prog)
1693 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1697 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1700 VM_Warning(prog, "PF_SV_AddStat: not enough memory\n");
1704 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1705 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1706 off = PRVM_G_INT (OFS_PARM2);
1711 VM_Warning(prog, "PF_SV_AddStat: index may not be less than 32\n");
1714 if(i >= (MAX_CL_STATS-32))
1716 VM_Warning(prog, "PF_SV_AddStat: index >= MAX_CL_STATS\n");
1719 if(i > (MAX_CL_STATS-32-4) && type == 1)
1721 VM_Warning(prog, "PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1724 vm_customstats[i].type = type;
1725 vm_customstats[i].fieldoffset = off;
1726 if(vm_customstats_last < i)
1727 vm_customstats_last = i;
1734 copies data from one entity to another
1736 copyentity(src, dst)
1739 static void VM_SV_copyentity(prvm_prog_t *prog)
1741 prvm_edict_t *in, *out;
1742 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1743 in = PRVM_G_EDICT(OFS_PARM0);
1744 if (in == prog->edicts)
1746 VM_Warning(prog, "copyentity: can not read world entity\n");
1749 if (in->priv.server->free)
1751 VM_Warning(prog, "copyentity: can not read free entity\n");
1754 out = PRVM_G_EDICT(OFS_PARM1);
1755 if (out == prog->edicts)
1757 VM_Warning(prog, "copyentity: can not modify world entity\n");
1760 if (out->priv.server->free)
1762 VM_Warning(prog, "copyentity: can not modify free entity\n");
1765 memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
1774 sets the color of a client and broadcasts the update to all connected clients
1776 setcolor(clientent, value)
1779 static void VM_SV_setcolor(prvm_prog_t *prog)
1784 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1785 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1786 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1788 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1790 Con_Print("tried to setcolor a non-client\n");
1794 client = svs.clients + entnum-1;
1797 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1798 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1801 if (client->old_colors != client->colors)
1803 client->old_colors = client->colors;
1804 // send notification to all clients
1805 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1806 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1807 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1815 effect(origin, modelname, startframe, framecount, framerate)
1818 static void VM_SV_effect(prvm_prog_t *prog)
1823 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1824 s = PRVM_G_STRING(OFS_PARM1);
1827 VM_Warning(prog, "effect: no model specified\n");
1831 i = SV_ModelIndex(s, 1);
1834 VM_Warning(prog, "effect: model not precached\n");
1838 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1840 VM_Warning(prog, "effect: framecount < 1\n");
1844 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1846 VM_Warning(prog, "effect: framerate < 1\n");
1850 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1851 SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1854 static void VM_SV_te_blood(prvm_prog_t *prog)
1856 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1857 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1859 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1860 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1862 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1863 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1864 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1866 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1867 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1868 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1870 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1871 SV_FlushBroadcastMessages();
1874 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1876 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1877 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1879 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1880 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1882 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1883 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1884 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1886 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1887 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1888 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1890 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1892 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1893 SV_FlushBroadcastMessages();
1896 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1898 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1899 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1900 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1906 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1907 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1908 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1909 SV_FlushBroadcastMessages();
1912 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1914 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1915 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1917 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1918 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1920 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1921 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1922 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1924 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1925 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1926 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1932 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1934 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1935 // gravity true/false
1936 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1939 SV_FlushBroadcastMessages();
1942 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1944 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1945 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1947 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1948 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1950 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1952 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1954 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1955 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1962 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1964 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1965 SV_FlushBroadcastMessages();
1968 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1970 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1971 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1973 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1974 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1976 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1977 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1978 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1980 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1984 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1985 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1988 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1990 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1991 SV_FlushBroadcastMessages();
1994 static void VM_SV_te_spark(prvm_prog_t *prog)
1996 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1997 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1999 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2000 MSG_WriteByte(&sv.datagram, TE_SPARK);
2002 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2004 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2006 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2007 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2008 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2010 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2011 SV_FlushBroadcastMessages();
2014 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2016 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2017 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2018 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2020 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2021 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2022 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2023 SV_FlushBroadcastMessages();
2026 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2028 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2029 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2030 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2032 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2033 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2034 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2035 SV_FlushBroadcastMessages();
2038 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2040 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2041 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2042 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2044 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2045 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2046 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2047 SV_FlushBroadcastMessages();
2050 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2052 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2053 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2054 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2056 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2058 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2059 SV_FlushBroadcastMessages();
2062 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2064 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2065 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2066 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2068 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2069 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2070 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2071 SV_FlushBroadcastMessages();
2074 static void VM_SV_te_customflash(prvm_prog_t *prog)
2076 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2077 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2079 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2080 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2082 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2083 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2084 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2086 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2088 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2090 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2091 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2092 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2093 SV_FlushBroadcastMessages();
2096 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2098 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2099 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2100 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2102 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2103 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2104 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2105 SV_FlushBroadcastMessages();
2108 static void VM_SV_te_spike(prvm_prog_t *prog)
2110 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2111 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2112 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2114 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2115 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2116 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2117 SV_FlushBroadcastMessages();
2120 static void VM_SV_te_superspike(prvm_prog_t *prog)
2122 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2123 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2124 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2126 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2127 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2128 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2129 SV_FlushBroadcastMessages();
2132 static void VM_SV_te_explosion(prvm_prog_t *prog)
2134 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2135 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2136 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2138 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2139 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2140 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2141 SV_FlushBroadcastMessages();
2144 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2146 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2147 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2148 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2150 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2151 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2152 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2153 SV_FlushBroadcastMessages();
2156 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2158 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2159 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2160 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2162 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2163 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2164 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2165 SV_FlushBroadcastMessages();
2168 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2170 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2171 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2172 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2174 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2175 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2176 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2177 SV_FlushBroadcastMessages();
2180 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2182 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2183 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2184 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2186 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2187 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2188 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2189 SV_FlushBroadcastMessages();
2192 static void VM_SV_te_teleport(prvm_prog_t *prog)
2194 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2195 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2196 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2198 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2199 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2200 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2201 SV_FlushBroadcastMessages();
2204 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2206 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2207 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2208 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2210 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2211 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2212 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2214 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2215 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2216 SV_FlushBroadcastMessages();
2219 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2221 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2222 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2223 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2225 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2227 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2231 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2232 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2234 SV_FlushBroadcastMessages();
2237 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2239 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2240 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2241 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2243 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2245 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2246 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2247 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2249 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2250 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2251 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2252 SV_FlushBroadcastMessages();
2255 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2257 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2258 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2259 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2261 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2263 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2264 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2265 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2267 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2268 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2269 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2270 SV_FlushBroadcastMessages();
2273 static void VM_SV_te_beam(prvm_prog_t *prog)
2275 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2276 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2277 MSG_WriteByte(&sv.datagram, TE_BEAM);
2279 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2281 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2282 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2283 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2285 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2286 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2287 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2288 SV_FlushBroadcastMessages();
2291 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2293 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2294 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2295 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2296 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2297 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2298 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2299 SV_FlushBroadcastMessages();
2302 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2304 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2305 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2306 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2308 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2309 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2310 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2312 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2313 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2314 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2316 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2317 SV_FlushBroadcastMessages();
2320 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2321 //this function originally written by KrimZon, made shorter by LordHavoc
2322 static void VM_SV_clientcommand(prvm_prog_t *prog)
2324 client_t *temp_client;
2326 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2328 //find client for this entity
2329 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2330 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2332 Con_Print("PF_clientcommand: entity is not a client\n");
2336 temp_client = host_client;
2337 host_client = svs.clients + i;
2338 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
2339 host_client = temp_client;
2342 //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)
2343 static void VM_SV_setattachment(prvm_prog_t *prog)
2345 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2346 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2347 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2350 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2352 if (e == prog->edicts)
2354 VM_Warning(prog, "setattachment: can not modify world entity\n");
2357 if (e->priv.server->free)
2359 VM_Warning(prog, "setattachment: can not modify free entity\n");
2363 if (tagentity == NULL)
2364 tagentity = prog->edicts;
2368 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2370 model = SV_GetModelFromEdict(tagentity);
2373 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2375 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);
2378 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));
2381 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2382 PRVM_serveredictfloat(e, tag_index) = tagindex;
2385 /////////////////////////////////////////
2386 // DP_MD3_TAGINFO extension coded by VorteX
2388 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2392 i = (int)PRVM_serveredictfloat(e, modelindex);
2393 if (i < 1 || i >= MAX_MODELS)
2396 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2399 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2406 Matrix4x4_CreateIdentity(tag_localmatrix);
2408 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2410 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2421 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2424 float pitchsign = 1;
2426 scale = PRVM_serveredictfloat(ent, scale);
2431 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);
2434 pitchsign = SV_GetPitchSign(prog, ent);
2435 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);
2439 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2442 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2444 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2445 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2446 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2447 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2449 *out = identitymatrix;
2453 // Warnings/errors code:
2454 // 0 - normal (everything all-right)
2457 // 3 - null or non-precached model
2458 // 4 - no tags with requested index
2459 // 5 - runaway loop at attachment chain
2460 extern cvar_t cl_bob;
2461 extern cvar_t cl_bobcycle;
2462 extern cvar_t cl_bobup;
2463 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2466 int modelindex, attachloop;
2467 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2470 *out = identitymatrix; // warnings and errors return identical matrix
2472 if (ent == prog->edicts)
2474 if (ent->priv.server->free)
2477 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2478 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2481 model = SV_GetModelByIndex(modelindex);
2483 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2484 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2485 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2487 tagmatrix = identitymatrix;
2488 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2492 if (attachloop >= 256) // prevent runaway looping
2494 // apply transformation by child's tagindex on parent entity and then
2495 // by parent entity itself
2496 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2497 if (ret && attachloop == 0)
2499 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2500 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2501 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2502 // next iteration we process the parent entity
2503 if (PRVM_serveredictedict(ent, tag_entity))
2505 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2506 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2513 // RENDER_VIEWMODEL magic
2514 if (PRVM_serveredictedict(ent, viewmodelforclient))
2516 Matrix4x4_Copy(&tagmatrix, out);
2517 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2519 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2520 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2523 // Cl_bob, ported from rendering code
2524 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2527 // LordHavoc: this code is *weird*, but not replacable (I think it
2528 // should be done in QC on the server, but oh well, quake is quake)
2529 // LordHavoc: figured out bobup: the time at which the sin is at 180
2530 // degrees (which allows lengthening or squishing the peak or valley)
2531 cycle = sv.time/cl_bobcycle.value;
2532 cycle -= (int)cycle;
2533 if (cycle < cl_bobup.value)
2534 cycle = sin(M_PI * cycle / cl_bobup.value);
2536 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2537 // bob is proportional to velocity in the xy plane
2538 // (don't count Z, or jumping messes it up)
2539 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;
2540 bob = bob*0.3 + bob*0.7*cycle;
2541 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2548 //float(entity ent, string tagname) gettagindex;
2550 static void VM_SV_gettagindex(prvm_prog_t *prog)
2553 const char *tag_name;
2556 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2558 ent = PRVM_G_EDICT(OFS_PARM0);
2559 tag_name = PRVM_G_STRING(OFS_PARM1);
2561 if (ent == prog->edicts)
2563 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2566 if (ent->priv.server->free)
2568 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2573 if (!SV_GetModelFromEdict(ent))
2574 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2577 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2579 if(developer_extra.integer)
2580 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2582 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2585 //vector(entity ent, float tagindex) gettaginfo;
2586 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2590 matrix4x4_t tag_matrix;
2591 matrix4x4_t tag_localmatrix;
2593 const char *tagname;
2595 vec3_t forward, left, up, origin;
2596 const dp_model_t *model;
2598 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2600 e = PRVM_G_EDICT(OFS_PARM0);
2601 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2603 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2604 Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
2605 VectorCopy(forward, PRVM_serverglobalvector(v_forward));
2606 VectorNegate(left, PRVM_serverglobalvector(v_right));
2607 VectorCopy(up, PRVM_serverglobalvector(v_up));
2608 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2609 model = SV_GetModelFromEdict(e);
2610 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2611 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2612 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2613 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2614 Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
2616 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2617 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2618 VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
2619 VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
2620 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2621 VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset));
2626 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2629 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2632 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2635 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2638 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2643 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2644 static void VM_SV_dropclient(prvm_prog_t *prog)
2647 client_t *oldhostclient;
2648 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2649 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2650 if (clientnum < 0 || clientnum >= svs.maxclients)
2652 VM_Warning(prog, "dropclient: not a client\n");
2655 if (!svs.clients[clientnum].active)
2657 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2660 oldhostclient = host_client;
2661 host_client = svs.clients + clientnum;
2662 SV_DropClient(false);
2663 host_client = oldhostclient;
2666 //entity() spawnclient (DP_SV_BOTCLIENT)
2667 static void VM_SV_spawnclient(prvm_prog_t *prog)
2671 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2672 prog->xfunction->builtinsprofile += 2;
2674 for (i = 0;i < svs.maxclients;i++)
2676 if (!svs.clients[i].active)
2678 prog->xfunction->builtinsprofile += 100;
2679 SV_ConnectClient (i, NULL);
2680 // this has to be set or else ClientDisconnect won't be called
2681 // we assume the qc will call ClientConnect...
2682 svs.clients[i].clientconnectcalled = true;
2683 ed = PRVM_EDICT_NUM(i + 1);
2687 VM_RETURN_EDICT(ed);
2690 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2691 static void VM_SV_clienttype(prvm_prog_t *prog)
2694 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2695 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2696 if (clientnum < 0 || clientnum >= svs.maxclients)
2697 PRVM_G_FLOAT(OFS_RETURN) = 3;
2698 else if (!svs.clients[clientnum].active)
2699 PRVM_G_FLOAT(OFS_RETURN) = 0;
2700 else if (svs.clients[clientnum].netconnection)
2701 PRVM_G_FLOAT(OFS_RETURN) = 1;
2703 PRVM_G_FLOAT(OFS_RETURN) = 2;
2710 string(string key) serverkey
2713 static void VM_SV_serverkey(prvm_prog_t *prog)
2715 char string[VM_STRINGTEMP_LENGTH];
2716 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2717 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2718 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2721 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2722 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2727 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2729 e = PRVM_G_EDICT(OFS_PARM0);
2730 if (e == prog->edicts)
2732 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2735 if (e->priv.server->free)
2737 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2740 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2741 if (i <= 0 || i >= MAX_MODELS)
2743 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2746 if (!sv.model_precache[i][0])
2748 VM_Warning(prog, "setmodelindex: model not precached\n");
2752 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2753 PRVM_serveredictfloat(e, modelindex) = i;
2755 mod = SV_GetModelByIndex(i);
2759 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2760 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2762 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2765 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2768 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2769 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2772 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2774 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2776 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2777 if (i <= 0 || i >= MAX_MODELS)
2779 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2782 if (!sv.model_precache[i][0])
2784 VM_Warning(prog, "modelnameforindex: model not precached\n");
2788 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2791 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2792 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2795 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2796 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2799 PRVM_G_FLOAT(OFS_RETURN) = i;
2802 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2803 static void VM_SV_trailparticles(prvm_prog_t *prog)
2806 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2808 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2811 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2812 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2813 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2814 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start);
2815 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end);
2816 MSG_WriteVector(&sv.datagram, start, sv.protocol);
2817 MSG_WriteVector(&sv.datagram, end, sv.protocol);
2818 SV_FlushBroadcastMessages();
2821 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2822 static void VM_SV_pointparticles(prvm_prog_t *prog)
2824 int effectnum, count;
2826 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2828 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2831 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2832 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2833 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2834 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2835 if (count == 1 && !VectorLength2(vel))
2838 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2839 MSG_WriteShort(&sv.datagram, effectnum);
2840 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2844 // 1+2+12+12+2=29 bytes
2845 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2846 MSG_WriteShort(&sv.datagram, effectnum);
2847 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2848 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2849 MSG_WriteShort(&sv.datagram, count);
2852 SV_FlushBroadcastMessages();
2855 //PF_setpause, // void(float pause) setpause = #531;
2856 static void VM_SV_setpause(prvm_prog_t *prog) {
2858 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2859 if (pauseValue != 0) { //pause the game
2861 sv.pausedstart = realtime;
2862 } else { //disable pause, in case it was enabled
2863 if (sv.paused != 0) {
2868 // send notification to all clients
2869 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2870 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2873 // #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.
2874 static void VM_SV_skel_create(prvm_prog_t *prog)
2876 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2877 dp_model_t *model = SV_GetModelByIndex(modelindex);
2878 skeleton_t *skeleton;
2880 PRVM_G_FLOAT(OFS_RETURN) = 0;
2881 if (!model || !model->num_bones)
2883 for (i = 0;i < MAX_EDICTS;i++)
2884 if (!prog->skeletons[i])
2886 if (i == MAX_EDICTS)
2888 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(prog->progs_mempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2889 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2890 skeleton->model = model;
2891 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2892 // initialize to identity matrices
2893 for (i = 0;i < skeleton->model->num_bones;i++)
2894 skeleton->relativetransforms[i] = identitymatrix;
2897 // #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
2898 static void VM_SV_skel_build(prvm_prog_t *prog)
2900 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2901 skeleton_t *skeleton;
2902 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2903 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2904 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2905 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2906 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2907 dp_model_t *model = SV_GetModelByIndex(modelindex);
2911 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2912 frameblend_t frameblend[MAX_FRAMEBLENDS];
2913 matrix4x4_t bonematrix;
2915 PRVM_G_FLOAT(OFS_RETURN) = 0;
2916 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2918 firstbone = max(0, firstbone);
2919 lastbone = min(lastbone, model->num_bones - 1);
2920 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2921 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2922 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time);
2923 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2925 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2927 memset(&bonematrix, 0, sizeof(bonematrix));
2928 for (blendindex = 0;blendindex < numblends;blendindex++)
2930 Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2931 Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp);
2933 Matrix4x4_Normalize3(&bonematrix, &bonematrix);
2934 Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac);
2936 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2939 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2940 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
2942 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2943 skeleton_t *skeleton;
2944 PRVM_G_FLOAT(OFS_RETURN) = 0;
2945 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2947 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2950 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2951 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
2953 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2954 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2955 skeleton_t *skeleton;
2956 PRVM_G_INT(OFS_RETURN) = 0;
2957 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2959 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2961 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
2964 // #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)
2965 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
2967 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2968 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2969 skeleton_t *skeleton;
2970 PRVM_G_FLOAT(OFS_RETURN) = 0;
2971 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2973 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2975 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2978 // #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
2979 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
2981 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2982 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2983 skeleton_t *skeleton;
2984 PRVM_G_FLOAT(OFS_RETURN) = 0;
2985 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2987 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2990 // #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)
2991 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
2993 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2994 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2995 skeleton_t *skeleton;
2997 vec3_t forward, left, up, origin;
2998 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2999 VectorClear(PRVM_clientglobalvector(v_forward));
3000 VectorClear(PRVM_clientglobalvector(v_right));
3001 VectorClear(PRVM_clientglobalvector(v_up));
3002 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3004 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3006 matrix = skeleton->relativetransforms[bonenum];
3007 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3008 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3009 VectorNegate(left, PRVM_clientglobalvector(v_right));
3010 VectorCopy(up, PRVM_clientglobalvector(v_up));
3011 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3014 // #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)
3015 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
3017 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3018 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3019 skeleton_t *skeleton;
3022 vec3_t forward, left, up, origin;
3023 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3024 VectorClear(PRVM_clientglobalvector(v_forward));
3025 VectorClear(PRVM_clientglobalvector(v_right));
3026 VectorClear(PRVM_clientglobalvector(v_up));
3027 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3029 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3031 matrix = skeleton->relativetransforms[bonenum];
3032 // convert to absolute
3033 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3036 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3038 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3039 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3040 VectorNegate(left, PRVM_clientglobalvector(v_right));
3041 VectorCopy(up, PRVM_clientglobalvector(v_up));
3042 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3045 // #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)
3046 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3048 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3049 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3050 vec3_t forward, left, up, origin;
3051 skeleton_t *skeleton;
3053 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3055 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3057 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3058 VectorNegate(PRVM_clientglobalvector(v_right), left);
3059 VectorCopy(PRVM_clientglobalvector(v_up), up);
3060 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3061 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3062 skeleton->relativetransforms[bonenum] = matrix;
3065 // #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)
3066 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3068 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3069 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3070 vec3_t forward, left, up, origin;
3071 skeleton_t *skeleton;
3074 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3076 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3078 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3079 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3080 VectorNegate(PRVM_clientglobalvector(v_right), left);
3081 VectorCopy(PRVM_clientglobalvector(v_up), up);
3082 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3083 temp = skeleton->relativetransforms[bonenum];
3084 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3087 // #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)
3088 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3090 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3091 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3092 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3094 vec3_t forward, left, up, origin;
3095 skeleton_t *skeleton;
3098 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3100 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3101 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3102 VectorNegate(PRVM_clientglobalvector(v_right), left);
3103 VectorCopy(PRVM_clientglobalvector(v_up), up);
3104 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3105 firstbone = max(0, firstbone);
3106 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3107 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3109 temp = skeleton->relativetransforms[bonenum];
3110 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3114 // #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
3115 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3117 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3118 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3119 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3120 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3122 skeleton_t *skeletondst;
3123 skeleton_t *skeletonsrc;
3124 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3126 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3128 firstbone = max(0, firstbone);
3129 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3130 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3131 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3132 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3135 // #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)
3136 static void VM_SV_skel_delete(prvm_prog_t *prog)
3138 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3139 skeleton_t *skeleton;
3140 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3143 prog->skeletons[skeletonindex] = NULL;
3146 // #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
3147 static void VM_SV_frameforname(prvm_prog_t *prog)
3149 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3150 dp_model_t *model = SV_GetModelByIndex(modelindex);
3151 const char *name = PRVM_G_STRING(OFS_PARM1);
3153 PRVM_G_FLOAT(OFS_RETURN) = -1;
3154 if (!model || !model->animscenes)
3156 for (i = 0;i < model->numframes;i++)
3158 if (!strcasecmp(model->animscenes[i].name, name))
3160 PRVM_G_FLOAT(OFS_RETURN) = i;
3166 // #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.
3167 static void VM_SV_frameduration(prvm_prog_t *prog)
3169 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3170 dp_model_t *model = SV_GetModelByIndex(modelindex);
3171 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3172 PRVM_G_FLOAT(OFS_RETURN) = 0;
3173 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3175 if (model->animscenes[framenum].framerate)
3176 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3180 prvm_builtin_t vm_sv_builtins[] = {
3181 NULL, // #0 NULL function (not callable) (QUAKE)
3182 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3183 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3184 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3185 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3186 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3187 VM_break, // #6 void() break (QUAKE)
3188 VM_random, // #7 float() random (QUAKE)
3189 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3190 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3191 VM_error, // #10 void(string e) error (QUAKE)
3192 VM_objerror, // #11 void(string e) objerror (QUAKE)
3193 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3194 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3195 VM_spawn, // #14 entity() spawn (QUAKE)
3196 VM_remove, // #15 void(entity e) remove (QUAKE)
3197 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3198 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3199 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3200 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3201 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3202 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3203 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3204 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3205 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3206 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3207 VM_ftos, // #26 string(float f) ftos (QUAKE)
3208 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3209 VM_coredump, // #28 void() coredump (QUAKE)
3210 VM_traceon, // #29 void() traceon (QUAKE)
3211 VM_traceoff, // #30 void() traceoff (QUAKE)
3212 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3213 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3214 NULL, // #33 (QUAKE)
3215 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3216 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3217 VM_rint, // #36 float(float v) rint (QUAKE)
3218 VM_floor, // #37 float(float v) floor (QUAKE)
3219 VM_ceil, // #38 float(float v) ceil (QUAKE)
3220 NULL, // #39 (QUAKE)
3221 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3222 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3223 NULL, // #42 (QUAKE)
3224 VM_fabs, // #43 float(float f) fabs (QUAKE)
3225 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3226 VM_cvar, // #45 float(string s) cvar (QUAKE)
3227 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3228 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3229 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3230 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3231 NULL, // #50 (QUAKE)
3232 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3233 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3234 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3235 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3236 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3237 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3238 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3239 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3240 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3241 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3242 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3243 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3244 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3245 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3246 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3247 NULL, // #66 (QUAKE)
3248 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3249 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3250 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3251 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3252 NULL, // #71 (QUAKE)
3253 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3254 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3255 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3256 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3257 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3258 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3259 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3260 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3261 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3262 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3263 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3264 NULL, // #83 (QUAKE)
3265 NULL, // #84 (QUAKE)
3266 NULL, // #85 (QUAKE)
3267 NULL, // #86 (QUAKE)
3268 NULL, // #87 (QUAKE)
3269 NULL, // #88 (QUAKE)
3270 NULL, // #89 (QUAKE)
3271 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3272 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3273 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3274 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3275 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3276 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3277 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3278 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3279 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3280 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3281 // FrikaC and Telejano range #100-#199
3292 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3293 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3294 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3295 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3296 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3297 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3298 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3299 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3300 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3301 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3382 // FTEQW range #200-#299
3401 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3404 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3405 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3406 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3407 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3408 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3409 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3410 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3411 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3412 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3413 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3415 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3423 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3446 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.
3447 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
3448 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3449 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3450 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)
3451 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
3452 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)
3453 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)
3454 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)
3455 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)
3456 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)
3457 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
3458 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)
3459 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
3460 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.
3483 // CSQC range #300-#399
3484 NULL, // #300 void() clearscene (EXT_CSQC)
3485 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3486 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3487 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3488 NULL, // #304 void() renderscene (EXT_CSQC)
3489 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3490 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3491 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3492 NULL, // #308 void() R_EndPolygon
3494 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3495 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3499 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3500 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3501 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3502 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3503 NULL, // #319 void(string name) freepic (EXT_CSQC)
3504 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3505 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3506 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3507 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3508 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3509 NULL, // #325 void(void) drawresetcliparea
3514 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3515 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3516 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3517 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3518 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3519 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3520 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3521 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3522 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3523 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3524 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3525 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3526 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3527 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3528 NULL, // #344 vector() getmousepos (EXT_CSQC)
3529 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3530 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3531 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3532 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3533 NULL, // #349 float() isdemo (EXT_CSQC)
3534 VM_isserver, // #350 float() isserver (EXT_CSQC)
3535 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3536 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3537 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3538 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3544 NULL, // #360 float() readbyte (EXT_CSQC)
3545 NULL, // #361 float() readchar (EXT_CSQC)
3546 NULL, // #362 float() readshort (EXT_CSQC)
3547 NULL, // #363 float() readlong (EXT_CSQC)
3548 NULL, // #364 float() readcoord (EXT_CSQC)
3549 NULL, // #365 float() readangle (EXT_CSQC)
3550 NULL, // #366 string() readstring (EXT_CSQC)
3551 NULL, // #367 float() readfloat (EXT_CSQC)
3584 // LordHavoc's range #400-#499
3585 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3586 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3587 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3588 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3589 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3590 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3591 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3592 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3593 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)
3594 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3595 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3596 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3597 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3598 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3599 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3600 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3601 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3602 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3603 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3604 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3605 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3606 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3607 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3608 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3609 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3610 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3611 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3612 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3613 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3614 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3615 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3616 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3617 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3618 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3619 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3620 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3621 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3622 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3623 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3624 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3625 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3626 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3627 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3628 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3629 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3630 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3631 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3632 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3633 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3634 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3635 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3636 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3637 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3638 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3639 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3640 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3641 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3642 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3644 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3645 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3646 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3647 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3648 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3649 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3650 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3651 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3652 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3653 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3654 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3656 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3657 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3658 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3659 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3660 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3661 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3662 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3663 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3664 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3665 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3666 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3667 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3668 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3669 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3670 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3671 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3679 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3680 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3681 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3682 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3683 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3684 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3685 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3686 VM_SV_WritePicture, // #501
3688 VM_whichpack, // #503 string(string) whichpack = #503;
3695 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3696 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3697 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3698 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)
3699 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3700 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3701 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3702 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3703 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3704 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3714 VM_loadfromdata, // #529
3715 VM_loadfromfile, // #530
3716 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3718 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3719 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3720 VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP)
3721 VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP)
3722 VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP)
3723 VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP)
3725 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3726 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3727 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3790 VM_callfunction, // #605
3791 VM_writetofile, // #606
3792 VM_isfunction, // #607
3798 VM_parseentitydata, // #613
3809 VM_SV_getextresponse, // #624 string getextresponse(void)
3812 VM_sprintf, // #627 string sprintf(string format, ...)
3813 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3814 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3824 VM_digest_hex, // #639
3828 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3830 void SVVM_init_cmd(prvm_prog_t *prog)
3835 void SVVM_reset_cmd(prvm_prog_t *prog)
3837 World_End(&sv.world);
3839 if(prog->loaded && PRVM_serverfunction(SV_Shutdown))
3841 func_t s = PRVM_serverfunction(SV_Shutdown);
3842 PRVM_serverglobalfloat(time) = sv.time;
3843 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3844 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");