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;
557 flags = PRVM_G_FLOAT(OFS_PARM6);
559 if (volume < 0 || volume > 255)
561 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
565 if (attenuation < 0 || attenuation > 4)
567 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
571 channel = CHAN_USER2ENGINE(channel);
573 if (!IS_CHAN(channel))
575 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
579 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANNELFLAG_RELIABLE, pitchchange);
586 Follows the same logic as VM_SV_sound, except instead of
587 an entity, an origin for the sound is provided, and channel
588 is omitted (since no entity is being tracked).
592 static void VM_SV_pointsound(prvm_prog_t *prog)
600 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
602 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
603 sample = PRVM_G_STRING(OFS_PARM1);
604 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
605 attenuation = PRVM_G_FLOAT(OFS_PARM3);
606 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
608 if (volume < 0 || volume > 255)
610 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
614 if (attenuation < 0 || attenuation > 4)
616 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
620 SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
627 Used for use tracing and shot targeting
628 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
629 if the tryents flag is set.
631 traceline (vector1, vector2, movetype, ignore)
634 static void VM_SV_traceline(prvm_prog_t *prog)
641 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
643 prog->xfunction->builtinsprofile += 30;
645 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
646 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), v2);
647 move = (int)PRVM_G_FLOAT(OFS_PARM2);
648 ent = PRVM_G_EDICT(OFS_PARM3);
650 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]))
651 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));
653 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
655 VM_SetTraceGlobals(prog, &trace);
663 Used for use tracing and shot targeting
664 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
665 if the tryents flag is set.
667 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
670 // LordHavoc: added this for my own use, VERY useful, similar to traceline
671 static void VM_SV_tracebox(prvm_prog_t *prog)
673 vec3_t v1, v2, m1, m2;
678 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
680 prog->xfunction->builtinsprofile += 30;
682 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
683 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), m1);
684 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), m2);
685 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), v2);
686 move = (int)PRVM_G_FLOAT(OFS_PARM4);
687 ent = PRVM_G_EDICT(OFS_PARM5);
689 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]))
690 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));
692 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
694 VM_SetTraceGlobals(prog, &trace);
697 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
701 vec3_t move, end, tossentorigin, tossentmins, tossentmaxs;
702 vec3_t original_origin;
703 vec3_t original_velocity;
704 vec3_t original_angles;
705 vec3_t original_avelocity;
708 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
709 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
710 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
711 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
713 gravity = PRVM_serveredictfloat(tossent, gravity);
716 gravity *= sv_gravity.value * 0.025;
718 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
720 SV_CheckVelocity (tossent);
721 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
722 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
723 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
724 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
725 VectorCopy(PRVM_serveredictvector(tossent, origin), tossentorigin);
726 VectorCopy(PRVM_serveredictvector(tossent, mins), tossentmins);
727 VectorCopy(PRVM_serveredictvector(tossent, maxs), tossentmaxs);
728 trace = SV_TraceBox(tossentorigin, tossentmins, tossentmaxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
729 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
730 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
732 if (trace.fraction < 1)
736 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
737 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
738 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
739 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
744 static void VM_SV_tracetoss(prvm_prog_t *prog)
748 prvm_edict_t *ignore;
750 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
752 prog->xfunction->builtinsprofile += 600;
754 ent = PRVM_G_EDICT(OFS_PARM0);
755 if (ent == prog->edicts)
757 VM_Warning(prog, "tracetoss: can not use world entity\n");
760 ignore = PRVM_G_EDICT(OFS_PARM1);
762 trace = SV_Trace_Toss(prog, ent, ignore);
764 VM_SetTraceGlobals(prog, &trace);
767 //============================================================================
769 static int checkpvsbytes;
770 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
772 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
778 // cycle to the next one
780 check = bound(1, check, svs.maxclients);
781 if (check == svs.maxclients)
789 prog->xfunction->builtinsprofile++;
791 if (i == svs.maxclients+1)
793 // look up the client's edict
794 ent = PRVM_EDICT_NUM(i);
795 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
796 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
798 // found a valid client (possibly the same one again)
802 // get the PVS for the entity
803 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
805 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
806 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
815 Returns a client (or object that has a client enemy) that would be a
818 If there is more than one valid option, they are cycled each frame
820 If (self.origin + self.viewofs) is not in the PVS of the current target,
821 it is not returned at all.
826 int c_invis, c_notvis;
827 static void VM_SV_checkclient(prvm_prog_t *prog)
829 prvm_edict_t *ent, *self;
832 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
834 // find a new check if on a new frame
835 if (sv.time - sv.lastchecktime >= 0.1)
837 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
838 sv.lastchecktime = sv.time;
841 // return check if it might be visible
842 ent = PRVM_EDICT_NUM(sv.lastcheck);
843 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
845 VM_RETURN_EDICT(prog->edicts);
849 // if current entity can't possibly see the check entity, return 0
850 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
851 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
852 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
855 VM_RETURN_EDICT(prog->edicts);
859 // might be able to see it
861 VM_RETURN_EDICT(ent);
864 //============================================================================
870 Checks if an entity is in a point's PVS.
871 Should be fast but can be inexact.
873 float checkpvs(vector viewpos, entity viewee) = #240;
876 static void VM_SV_checkpvs(prvm_prog_t *prog)
878 vec3_t viewpos, absmin, absmax;
879 prvm_edict_t *viewee;
884 unsigned char fatpvs[MAX_MAP_LEAFS/8];
887 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
888 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
889 viewee = PRVM_G_EDICT(OFS_PARM1);
891 if(viewee->priv.server->free)
893 VM_Warning(prog, "checkpvs: can not check free entity\n");
894 PRVM_G_FLOAT(OFS_RETURN) = 4;
899 if(!sv.worldmodel || !sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
901 // no PVS support on this worldmodel... darn
902 PRVM_G_FLOAT(OFS_RETURN) = 3;
905 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
908 // viewpos isn't in any PVS... darn
909 PRVM_G_FLOAT(OFS_RETURN) = 2;
912 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
913 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
914 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, absmin, absmax);
916 // using fat PVS like FTEQW does (slow)
917 if(!sv.worldmodel || !sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
919 // no PVS support on this worldmodel... darn
920 PRVM_G_FLOAT(OFS_RETURN) = 3;
923 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
926 // viewpos isn't in any PVS... darn
927 PRVM_G_FLOAT(OFS_RETURN) = 2;
930 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
931 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
932 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, absmin, absmax);
941 Sends text over to the client's execution buffer
943 stuffcmd (clientent, value, ...)
946 static void VM_SV_stuffcmd(prvm_prog_t *prog)
950 char string[VM_STRINGTEMP_LENGTH];
952 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
954 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
955 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
957 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
961 VM_VarString(prog, 1, string, sizeof(string));
964 host_client = svs.clients + entnum-1;
965 Host_ClientCommands ("%s", string);
973 Returns a chain of entities that have origins within a spherical area
975 findradius (origin, radius)
978 static void VM_SV_findradius(prvm_prog_t *prog)
980 prvm_edict_t *ent, *chain;
981 vec_t radius, radius2;
982 vec3_t org, eorg, mins, maxs;
985 static prvm_edict_t *touchedicts[MAX_EDICTS];
988 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
991 chainfield = PRVM_G_INT(OFS_PARM2);
993 chainfield = prog->fieldoffsets.chain;
995 prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
997 chain = (prvm_edict_t *)prog->edicts;
999 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1000 radius = PRVM_G_FLOAT(OFS_PARM1);
1001 radius2 = radius * radius;
1003 mins[0] = org[0] - (radius + 1);
1004 mins[1] = org[1] - (radius + 1);
1005 mins[2] = org[2] - (radius + 1);
1006 maxs[0] = org[0] + (radius + 1);
1007 maxs[1] = org[1] + (radius + 1);
1008 maxs[2] = org[2] + (radius + 1);
1009 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1010 if (numtouchedicts > MAX_EDICTS)
1012 // this never happens
1013 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1014 numtouchedicts = MAX_EDICTS;
1016 for (i = 0;i < numtouchedicts;i++)
1018 ent = touchedicts[i];
1019 prog->xfunction->builtinsprofile++;
1020 // Quake did not return non-solid entities but darkplaces does
1021 // (note: this is the reason you can't blow up fallen zombies)
1022 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1024 // LordHavoc: compare against bounding box rather than center so it
1025 // doesn't miss large objects, and use DotProduct instead of Length
1026 // for a major speedup
1027 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1028 if (sv_gameplayfix_findradiusdistancetobox.integer)
1030 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1031 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1032 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1035 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1036 if (DotProduct(eorg, eorg) < radius2)
1038 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1043 VM_RETURN_EDICT(chain);
1046 static void VM_SV_precache_sound(prvm_prog_t *prog)
1048 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1049 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1052 static void VM_SV_precache_model(prvm_prog_t *prog)
1054 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1055 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1056 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1063 float(float yaw, float dist[, settrace]) walkmove
1066 static void VM_SV_walkmove(prvm_prog_t *prog)
1075 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1077 // assume failure if it returns early
1078 PRVM_G_FLOAT(OFS_RETURN) = 0;
1080 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1081 if (ent == prog->edicts)
1083 VM_Warning(prog, "walkmove: can not modify world entity\n");
1086 if (ent->priv.server->free)
1088 VM_Warning(prog, "walkmove: can not modify free entity\n");
1091 yaw = PRVM_G_FLOAT(OFS_PARM0);
1092 dist = PRVM_G_FLOAT(OFS_PARM1);
1093 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1095 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1098 yaw = yaw*M_PI*2 / 360;
1100 move[0] = cos(yaw)*dist;
1101 move[1] = sin(yaw)*dist;
1104 // save program state, because SV_movestep may call other progs
1105 oldf = prog->xfunction;
1106 oldself = PRVM_serverglobaledict(self);
1108 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1111 // restore program state
1112 prog->xfunction = oldf;
1113 PRVM_serverglobaledict(self) = oldself;
1124 static void VM_SV_droptofloor(prvm_prog_t *prog)
1127 vec3_t end, entorigin, entmins, entmaxs;
1130 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1132 // assume failure if it returns early
1133 PRVM_G_FLOAT(OFS_RETURN) = 0;
1135 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1136 if (ent == prog->edicts)
1138 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1141 if (ent->priv.server->free)
1143 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1147 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1150 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1151 SV_NudgeOutOfSolid(ent);
1153 VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
1154 VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
1155 VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
1156 trace = SV_TraceBox(entorigin, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1157 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1160 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]);
1161 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1162 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1163 VectorSubtract(trace.endpos, offset, trace.endpos);
1164 if (trace.startsolid)
1166 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]);
1168 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1169 PRVM_serveredictedict(ent, groundentity) = 0;
1170 PRVM_G_FLOAT(OFS_RETURN) = 1;
1172 else if (trace.fraction < 1)
1174 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]);
1175 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1176 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1177 SV_NudgeOutOfSolid(ent);
1179 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1180 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1181 PRVM_G_FLOAT(OFS_RETURN) = 1;
1182 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1183 ent->priv.server->suspendedinairflag = true;
1188 if (!trace.allsolid && trace.fraction < 1)
1190 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1192 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1193 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1194 PRVM_G_FLOAT(OFS_RETURN) = 1;
1195 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1196 ent->priv.server->suspendedinairflag = true;
1205 void(float style, string value) lightstyle
1208 static void VM_SV_lightstyle(prvm_prog_t *prog)
1215 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1217 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1218 val = PRVM_G_STRING(OFS_PARM1);
1220 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1221 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1224 // change the string in sv
1225 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1227 // send message to all clients on this server
1228 if (sv.state != ss_active)
1231 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1233 if (client->active && client->netconnection)
1235 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1236 MSG_WriteChar (&client->netconnection->message,style);
1237 MSG_WriteString (&client->netconnection->message, val);
1247 static void VM_SV_checkbottom(prvm_prog_t *prog)
1249 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1250 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1258 static void VM_SV_pointcontents(prvm_prog_t *prog)
1261 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1262 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point);
1263 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(point));
1270 Pick a vector for the player to shoot along
1271 vector aim(entity, missilespeed)
1274 static void VM_SV_aim(prvm_prog_t *prog)
1276 prvm_edict_t *ent, *check, *bestent;
1277 vec3_t start, dir, end, bestdir;
1280 float dist, bestdist;
1283 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1285 // assume failure if it returns early
1286 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1287 // if sv_aim is so high it can't possibly accept anything, skip out early
1288 if (sv_aim.value >= 1)
1291 ent = PRVM_G_EDICT(OFS_PARM0);
1292 if (ent == prog->edicts)
1294 VM_Warning(prog, "aim: can not use world entity\n");
1297 if (ent->priv.server->free)
1299 VM_Warning(prog, "aim: can not use free entity\n");
1302 //speed = PRVM_G_FLOAT(OFS_PARM1);
1304 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1307 // try sending a trace straight
1308 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1309 VectorMA (start, 2048, dir, end);
1310 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1311 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1312 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1314 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1319 // try all possible entities
1320 VectorCopy (dir, bestdir);
1321 bestdist = sv_aim.value;
1324 check = PRVM_NEXT_EDICT(prog->edicts);
1325 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1327 prog->xfunction->builtinsprofile++;
1328 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1332 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1333 continue; // don't aim at teammate
1334 for (j=0 ; j<3 ; j++)
1335 end[j] = PRVM_serveredictvector(check, origin)[j]
1336 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1337 VectorSubtract (end, start, dir);
1338 VectorNormalize (dir);
1339 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1340 if (dist < bestdist)
1341 continue; // to far to turn
1342 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1343 if (tr.ent == check)
1344 { // can shoot at this one
1352 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1353 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1354 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1356 VectorNormalize (end);
1357 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1361 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1366 ===============================================================================
1370 ===============================================================================
1373 #define MSG_BROADCAST 0 // unreliable to all
1374 #define MSG_ONE 1 // reliable to one (msg_entity)
1375 #define MSG_ALL 2 // reliable to all
1376 #define MSG_INIT 3 // write to the init string
1377 #define MSG_ENTITY 5
1379 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1385 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1389 return &sv.datagram;
1392 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1393 entnum = PRVM_NUM_FOR_EDICT(ent);
1394 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1396 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1397 return &sv.reliable_datagram;
1400 return &svs.clients[entnum-1].netconnection->message;
1403 VM_Warning(prog, "WriteDest: bad destination\n");
1405 return &sv.reliable_datagram;
1411 return sv.writeentitiestoclient_msg;
1417 static void VM_SV_WriteByte(prvm_prog_t *prog)
1419 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1420 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1423 static void VM_SV_WriteChar(prvm_prog_t *prog)
1425 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1426 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1429 static void VM_SV_WriteShort(prvm_prog_t *prog)
1431 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1432 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1435 static void VM_SV_WriteLong(prvm_prog_t *prog)
1437 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1438 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1441 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1443 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1444 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1447 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1449 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1450 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1453 static void VM_SV_WriteString(prvm_prog_t *prog)
1455 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1456 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1459 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1461 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1462 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1466 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1468 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1469 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1472 // writes a picture as at most size bytes of data
1474 // IMGNAME \0 SIZE(short) IMGDATA
1475 // if failed to read/compress:
1477 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1478 static void VM_SV_WritePicture(prvm_prog_t *prog)
1480 const char *imgname;
1484 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1486 imgname = PRVM_G_STRING(OFS_PARM1);
1487 size = (size_t) PRVM_G_FLOAT(OFS_PARM2);
1491 MSG_WriteString(WriteDest(prog), imgname);
1492 if(Image_Compress(imgname, size, &buf, &size))
1495 MSG_WriteShort(WriteDest(prog), size);
1496 SZ_Write(WriteDest(prog), (unsigned char *) buf, size);
1501 MSG_WriteShort(WriteDest(prog), 0);
1505 //////////////////////////////////////////////////////////
1507 static void VM_SV_makestatic(prvm_prog_t *prog)
1512 // allow 0 parameters due to an id1 qc bug in which this function is used
1513 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1514 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1516 if (prog->argc >= 1)
1517 ent = PRVM_G_EDICT(OFS_PARM0);
1519 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1520 if (ent == prog->edicts)
1522 VM_Warning(prog, "makestatic: can not modify world entity\n");
1525 if (ent->priv.server->free)
1527 VM_Warning(prog, "makestatic: can not modify free entity\n");
1532 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1537 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1538 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1539 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1541 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1543 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1544 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1545 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1549 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1550 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1551 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1554 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1555 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1556 for (i=0 ; i<3 ; i++)
1558 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1559 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1562 // throw the entity away now
1563 PRVM_ED_Free(prog, ent);
1566 //=============================================================================
1573 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1579 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1581 ent = PRVM_G_EDICT(OFS_PARM0);
1582 i = PRVM_NUM_FOR_EDICT(ent);
1583 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1585 Con_Print("tried to setspawnparms on a non-client\n");
1589 // copy spawn parms out of the client_t
1590 client = svs.clients + i-1;
1591 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1592 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1599 Returns a color vector indicating the lighting at the requested point.
1601 (Internal Operation note: actually measures the light beneath the point, just like
1602 the model lighting on the client)
1607 static void VM_SV_getlight(prvm_prog_t *prog)
1609 vec3_t ambientcolor, diffusecolor, diffusenormal;
1611 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1612 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
1613 VectorClear(ambientcolor);
1614 VectorClear(diffusecolor);
1615 VectorClear(diffusenormal);
1616 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1617 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1618 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1623 unsigned char type; // 1/2/8 or other value if isn't used
1627 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1628 static int vm_customstats_last;
1630 void VM_CustomStats_Clear (void)
1634 Z_Free(vm_customstats);
1635 vm_customstats = NULL;
1636 vm_customstats_last = -1;
1640 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1642 prvm_prog_t *prog = SVVM_prog;
1649 for(i=0; i<vm_customstats_last+1 ;i++)
1651 if(!vm_customstats[i].type)
1653 switch(vm_customstats[i].type)
1655 //string as 16 bytes
1658 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1659 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1660 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1661 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1662 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1664 //float field sent as-is
1666 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1668 //integer value of float field
1670 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1678 // void(float index, float type, .void field) SV_AddStat = #232;
1679 // Set up an auto-sent player stat.
1680 // Client's get thier own fields sent to them. Index may not be less than 32.
1681 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1682 // 1: string (4 stats carrying a total of 16 charactures)
1683 // 2: float (one stat, float converted to an integer for transportation)
1684 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1685 static void VM_SV_AddStat(prvm_prog_t *prog)
1690 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1694 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1697 VM_Warning(prog, "PF_SV_AddStat: not enough memory\n");
1701 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1702 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1703 off = PRVM_G_INT (OFS_PARM2);
1708 VM_Warning(prog, "PF_SV_AddStat: index may not be less than 32\n");
1711 if(i >= (MAX_CL_STATS-32))
1713 VM_Warning(prog, "PF_SV_AddStat: index >= MAX_CL_STATS\n");
1716 if(i > (MAX_CL_STATS-32-4) && type == 1)
1718 VM_Warning(prog, "PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1721 vm_customstats[i].type = type;
1722 vm_customstats[i].fieldoffset = off;
1723 if(vm_customstats_last < i)
1724 vm_customstats_last = i;
1731 copies data from one entity to another
1733 copyentity(src, dst)
1736 static void VM_SV_copyentity(prvm_prog_t *prog)
1738 prvm_edict_t *in, *out;
1739 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1740 in = PRVM_G_EDICT(OFS_PARM0);
1741 if (in == prog->edicts)
1743 VM_Warning(prog, "copyentity: can not read world entity\n");
1746 if (in->priv.server->free)
1748 VM_Warning(prog, "copyentity: can not read free entity\n");
1751 out = PRVM_G_EDICT(OFS_PARM1);
1752 if (out == prog->edicts)
1754 VM_Warning(prog, "copyentity: can not modify world entity\n");
1757 if (out->priv.server->free)
1759 VM_Warning(prog, "copyentity: can not modify free entity\n");
1762 memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
1771 sets the color of a client and broadcasts the update to all connected clients
1773 setcolor(clientent, value)
1776 static void VM_SV_setcolor(prvm_prog_t *prog)
1781 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1782 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1783 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1785 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1787 Con_Print("tried to setcolor a non-client\n");
1791 client = svs.clients + entnum-1;
1794 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1795 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1798 if (client->old_colors != client->colors)
1800 client->old_colors = client->colors;
1801 // send notification to all clients
1802 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1803 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1804 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1812 effect(origin, modelname, startframe, framecount, framerate)
1815 static void VM_SV_effect(prvm_prog_t *prog)
1820 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1821 s = PRVM_G_STRING(OFS_PARM1);
1824 VM_Warning(prog, "effect: no model specified\n");
1828 i = SV_ModelIndex(s, 1);
1831 VM_Warning(prog, "effect: model not precached\n");
1835 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1837 VM_Warning(prog, "effect: framecount < 1\n");
1841 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1843 VM_Warning(prog, "effect: framerate < 1\n");
1847 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1848 SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1851 static void VM_SV_te_blood(prvm_prog_t *prog)
1853 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1854 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1856 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1857 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1859 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1860 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1861 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1863 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1864 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1865 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1867 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1868 SV_FlushBroadcastMessages();
1871 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1873 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1874 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1876 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1877 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1879 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1880 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1881 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1883 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1884 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1885 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1887 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1889 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1890 SV_FlushBroadcastMessages();
1893 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1895 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1896 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1897 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1900 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1903 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1904 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1905 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1906 SV_FlushBroadcastMessages();
1909 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1911 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1912 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1914 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1915 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1917 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1918 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1919 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1921 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1922 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1923 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1925 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1926 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1929 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1931 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1932 // gravity true/false
1933 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1936 SV_FlushBroadcastMessages();
1939 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1941 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1942 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1944 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1945 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1948 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1949 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1952 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1953 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1955 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1959 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1961 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1962 SV_FlushBroadcastMessages();
1965 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1967 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1968 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1970 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1971 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1973 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1974 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1975 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1977 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1978 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1979 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1983 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1985 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1987 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1988 SV_FlushBroadcastMessages();
1991 static void VM_SV_te_spark(prvm_prog_t *prog)
1993 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1994 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1996 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1997 MSG_WriteByte(&sv.datagram, TE_SPARK);
1999 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2000 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2001 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2003 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2004 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2005 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2007 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2008 SV_FlushBroadcastMessages();
2011 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2013 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2014 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2015 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2017 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2018 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2019 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2020 SV_FlushBroadcastMessages();
2023 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2025 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2026 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2027 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2029 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2030 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2031 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2032 SV_FlushBroadcastMessages();
2035 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2037 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2038 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2039 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2041 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2042 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2043 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2044 SV_FlushBroadcastMessages();
2047 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2049 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2050 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2051 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2054 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2055 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2056 SV_FlushBroadcastMessages();
2059 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2061 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2062 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2063 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2065 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2066 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2067 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2068 SV_FlushBroadcastMessages();
2071 static void VM_SV_te_customflash(prvm_prog_t *prog)
2073 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2074 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2076 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2077 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2079 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2080 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2081 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2083 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2085 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2087 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2088 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2089 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2090 SV_FlushBroadcastMessages();
2093 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2095 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2096 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2097 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2099 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2100 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2101 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2102 SV_FlushBroadcastMessages();
2105 static void VM_SV_te_spike(prvm_prog_t *prog)
2107 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2108 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2109 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2111 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2112 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2113 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2114 SV_FlushBroadcastMessages();
2117 static void VM_SV_te_superspike(prvm_prog_t *prog)
2119 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2120 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2121 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2123 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2124 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2125 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2126 SV_FlushBroadcastMessages();
2129 static void VM_SV_te_explosion(prvm_prog_t *prog)
2131 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2132 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2133 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2135 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2136 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2137 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2138 SV_FlushBroadcastMessages();
2141 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2143 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2144 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2145 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2147 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2148 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2149 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2150 SV_FlushBroadcastMessages();
2153 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2155 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2156 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2157 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2159 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2160 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2161 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2162 SV_FlushBroadcastMessages();
2165 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2167 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2168 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2169 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2171 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2172 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2173 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2174 SV_FlushBroadcastMessages();
2177 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2179 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2180 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2181 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2183 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2184 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2185 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2186 SV_FlushBroadcastMessages();
2189 static void VM_SV_te_teleport(prvm_prog_t *prog)
2191 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2192 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2193 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2195 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2196 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2197 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2198 SV_FlushBroadcastMessages();
2201 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2203 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2204 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2205 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2207 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2208 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2209 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2211 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2212 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2213 SV_FlushBroadcastMessages();
2216 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2218 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2219 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2220 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2222 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2224 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2225 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2226 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2230 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2231 SV_FlushBroadcastMessages();
2234 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2236 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2237 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2238 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2240 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2242 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2243 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2244 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2246 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2247 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2248 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2249 SV_FlushBroadcastMessages();
2252 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2254 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2255 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2256 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2258 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2260 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2261 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2262 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2264 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2265 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2266 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2267 SV_FlushBroadcastMessages();
2270 static void VM_SV_te_beam(prvm_prog_t *prog)
2272 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2273 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2274 MSG_WriteByte(&sv.datagram, TE_BEAM);
2276 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2278 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2279 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2280 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2282 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2283 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2284 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2285 SV_FlushBroadcastMessages();
2288 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2290 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2291 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2292 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2293 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2294 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2295 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2296 SV_FlushBroadcastMessages();
2299 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2301 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2302 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2303 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2305 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2306 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2307 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2309 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2310 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2311 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2313 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2314 SV_FlushBroadcastMessages();
2317 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2318 //this function originally written by KrimZon, made shorter by LordHavoc
2319 static void VM_SV_clientcommand(prvm_prog_t *prog)
2321 client_t *temp_client;
2323 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2325 //find client for this entity
2326 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2327 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2329 Con_Print("PF_clientcommand: entity is not a client\n");
2333 temp_client = host_client;
2334 host_client = svs.clients + i;
2335 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
2336 host_client = temp_client;
2339 //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)
2340 static void VM_SV_setattachment(prvm_prog_t *prog)
2342 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2343 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2344 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2347 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2349 if (e == prog->edicts)
2351 VM_Warning(prog, "setattachment: can not modify world entity\n");
2354 if (e->priv.server->free)
2356 VM_Warning(prog, "setattachment: can not modify free entity\n");
2360 if (tagentity == NULL)
2361 tagentity = prog->edicts;
2365 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2367 model = SV_GetModelFromEdict(tagentity);
2370 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2372 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);
2375 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));
2378 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2379 PRVM_serveredictfloat(e, tag_index) = tagindex;
2382 /////////////////////////////////////////
2383 // DP_MD3_TAGINFO extension coded by VorteX
2385 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2389 i = (int)PRVM_serveredictfloat(e, modelindex);
2390 if (i < 1 || i >= MAX_MODELS)
2393 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2396 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2403 Matrix4x4_CreateIdentity(tag_localmatrix);
2405 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2407 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2418 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2421 float pitchsign = 1;
2423 scale = PRVM_serveredictfloat(ent, scale);
2428 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);
2431 pitchsign = SV_GetPitchSign(prog, ent);
2432 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);
2436 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2439 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2441 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2442 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2443 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2444 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2446 *out = identitymatrix;
2450 // Warnings/errors code:
2451 // 0 - normal (everything all-right)
2454 // 3 - null or non-precached model
2455 // 4 - no tags with requested index
2456 // 5 - runaway loop at attachment chain
2457 extern cvar_t cl_bob;
2458 extern cvar_t cl_bobcycle;
2459 extern cvar_t cl_bobup;
2460 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2463 int modelindex, attachloop;
2464 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2467 *out = identitymatrix; // warnings and errors return identical matrix
2469 if (ent == prog->edicts)
2471 if (ent->priv.server->free)
2474 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2475 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2478 model = SV_GetModelByIndex(modelindex);
2480 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2481 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2482 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2484 tagmatrix = identitymatrix;
2485 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2489 if (attachloop >= 256) // prevent runaway looping
2491 // apply transformation by child's tagindex on parent entity and then
2492 // by parent entity itself
2493 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2494 if (ret && attachloop == 0)
2496 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2497 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2498 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2499 // next iteration we process the parent entity
2500 if (PRVM_serveredictedict(ent, tag_entity))
2502 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2503 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2510 // RENDER_VIEWMODEL magic
2511 if (PRVM_serveredictedict(ent, viewmodelforclient))
2513 Matrix4x4_Copy(&tagmatrix, out);
2514 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2516 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2517 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2520 // Cl_bob, ported from rendering code
2521 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2524 // LordHavoc: this code is *weird*, but not replacable (I think it
2525 // should be done in QC on the server, but oh well, quake is quake)
2526 // LordHavoc: figured out bobup: the time at which the sin is at 180
2527 // degrees (which allows lengthening or squishing the peak or valley)
2528 cycle = sv.time/cl_bobcycle.value;
2529 cycle -= (int)cycle;
2530 if (cycle < cl_bobup.value)
2531 cycle = sin(M_PI * cycle / cl_bobup.value);
2533 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2534 // bob is proportional to velocity in the xy plane
2535 // (don't count Z, or jumping messes it up)
2536 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;
2537 bob = bob*0.3 + bob*0.7*cycle;
2538 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2545 //float(entity ent, string tagname) gettagindex;
2547 static void VM_SV_gettagindex(prvm_prog_t *prog)
2550 const char *tag_name;
2553 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2555 ent = PRVM_G_EDICT(OFS_PARM0);
2556 tag_name = PRVM_G_STRING(OFS_PARM1);
2558 if (ent == prog->edicts)
2560 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2563 if (ent->priv.server->free)
2565 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2570 if (!SV_GetModelFromEdict(ent))
2571 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2574 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2576 if(developer_extra.integer)
2577 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2579 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2582 //vector(entity ent, float tagindex) gettaginfo;
2583 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2587 matrix4x4_t tag_matrix;
2588 matrix4x4_t tag_localmatrix;
2590 const char *tagname;
2592 vec3_t forward, left, up, origin;
2593 const dp_model_t *model;
2595 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2597 e = PRVM_G_EDICT(OFS_PARM0);
2598 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2600 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2601 Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
2602 VectorCopy(forward, PRVM_serverglobalvector(v_forward));
2603 VectorNegate(left, PRVM_serverglobalvector(v_right));
2604 VectorCopy(up, PRVM_serverglobalvector(v_up));
2605 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2606 model = SV_GetModelFromEdict(e);
2607 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2608 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2609 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2610 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2611 Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
2613 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2614 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2615 VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
2616 VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
2617 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2618 VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset));
2623 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2626 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2629 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2632 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2635 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2640 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2641 static void VM_SV_dropclient(prvm_prog_t *prog)
2644 client_t *oldhostclient;
2645 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2646 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2647 if (clientnum < 0 || clientnum >= svs.maxclients)
2649 VM_Warning(prog, "dropclient: not a client\n");
2652 if (!svs.clients[clientnum].active)
2654 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2657 oldhostclient = host_client;
2658 host_client = svs.clients + clientnum;
2659 SV_DropClient(false);
2660 host_client = oldhostclient;
2663 //entity() spawnclient (DP_SV_BOTCLIENT)
2664 static void VM_SV_spawnclient(prvm_prog_t *prog)
2668 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2669 prog->xfunction->builtinsprofile += 2;
2671 for (i = 0;i < svs.maxclients;i++)
2673 if (!svs.clients[i].active)
2675 prog->xfunction->builtinsprofile += 100;
2676 SV_ConnectClient (i, NULL);
2677 // this has to be set or else ClientDisconnect won't be called
2678 // we assume the qc will call ClientConnect...
2679 svs.clients[i].clientconnectcalled = true;
2680 ed = PRVM_EDICT_NUM(i + 1);
2684 VM_RETURN_EDICT(ed);
2687 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2688 static void VM_SV_clienttype(prvm_prog_t *prog)
2691 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2692 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2693 if (clientnum < 0 || clientnum >= svs.maxclients)
2694 PRVM_G_FLOAT(OFS_RETURN) = 3;
2695 else if (!svs.clients[clientnum].active)
2696 PRVM_G_FLOAT(OFS_RETURN) = 0;
2697 else if (svs.clients[clientnum].netconnection)
2698 PRVM_G_FLOAT(OFS_RETURN) = 1;
2700 PRVM_G_FLOAT(OFS_RETURN) = 2;
2707 string(string key) serverkey
2710 static void VM_SV_serverkey(prvm_prog_t *prog)
2712 char string[VM_STRINGTEMP_LENGTH];
2713 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2714 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2715 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2718 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2719 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2724 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2726 e = PRVM_G_EDICT(OFS_PARM0);
2727 if (e == prog->edicts)
2729 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2732 if (e->priv.server->free)
2734 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2737 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2738 if (i <= 0 || i >= MAX_MODELS)
2740 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2743 if (!sv.model_precache[i][0])
2745 VM_Warning(prog, "setmodelindex: model not precached\n");
2749 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2750 PRVM_serveredictfloat(e, modelindex) = i;
2752 mod = SV_GetModelByIndex(i);
2756 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2757 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2759 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2762 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2765 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2766 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2769 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2771 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2773 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2774 if (i <= 0 || i >= MAX_MODELS)
2776 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2779 if (!sv.model_precache[i][0])
2781 VM_Warning(prog, "modelnameforindex: model not precached\n");
2785 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2788 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2789 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2792 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2793 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2796 PRVM_G_FLOAT(OFS_RETURN) = i;
2799 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2800 static void VM_SV_trailparticles(prvm_prog_t *prog)
2803 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2805 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2808 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2809 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2810 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2811 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start);
2812 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end);
2813 MSG_WriteVector(&sv.datagram, start, sv.protocol);
2814 MSG_WriteVector(&sv.datagram, end, sv.protocol);
2815 SV_FlushBroadcastMessages();
2818 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2819 static void VM_SV_pointparticles(prvm_prog_t *prog)
2821 int effectnum, count;
2823 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2825 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2828 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2829 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2830 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2831 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2832 if (count == 1 && !VectorLength2(vel))
2835 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2836 MSG_WriteShort(&sv.datagram, effectnum);
2837 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2841 // 1+2+12+12+2=29 bytes
2842 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2843 MSG_WriteShort(&sv.datagram, effectnum);
2844 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2845 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2846 MSG_WriteShort(&sv.datagram, count);
2849 SV_FlushBroadcastMessages();
2852 //PF_setpause, // void(float pause) setpause = #531;
2853 static void VM_SV_setpause(prvm_prog_t *prog) {
2855 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2856 if (pauseValue != 0) { //pause the game
2858 sv.pausedstart = realtime;
2859 } else { //disable pause, in case it was enabled
2860 if (sv.paused != 0) {
2865 // send notification to all clients
2866 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2867 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2870 // #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.
2871 static void VM_SV_skel_create(prvm_prog_t *prog)
2873 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2874 dp_model_t *model = SV_GetModelByIndex(modelindex);
2875 skeleton_t *skeleton;
2877 PRVM_G_FLOAT(OFS_RETURN) = 0;
2878 if (!model || !model->num_bones)
2880 for (i = 0;i < MAX_EDICTS;i++)
2881 if (!prog->skeletons[i])
2883 if (i == MAX_EDICTS)
2885 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(prog->progs_mempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2886 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2887 skeleton->model = model;
2888 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2889 // initialize to identity matrices
2890 for (i = 0;i < skeleton->model->num_bones;i++)
2891 skeleton->relativetransforms[i] = identitymatrix;
2894 // #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
2895 static void VM_SV_skel_build(prvm_prog_t *prog)
2897 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2898 skeleton_t *skeleton;
2899 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2900 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2901 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2902 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2903 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2904 dp_model_t *model = SV_GetModelByIndex(modelindex);
2908 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2909 frameblend_t frameblend[MAX_FRAMEBLENDS];
2910 matrix4x4_t bonematrix;
2912 PRVM_G_FLOAT(OFS_RETURN) = 0;
2913 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2915 firstbone = max(0, firstbone);
2916 lastbone = min(lastbone, model->num_bones - 1);
2917 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2918 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2919 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time);
2920 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2922 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2924 memset(&bonematrix, 0, sizeof(bonematrix));
2925 for (blendindex = 0;blendindex < numblends;blendindex++)
2927 Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2928 Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp);
2930 Matrix4x4_Normalize3(&bonematrix, &bonematrix);
2931 Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac);
2933 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2936 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2937 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
2939 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2940 skeleton_t *skeleton;
2941 PRVM_G_FLOAT(OFS_RETURN) = 0;
2942 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2944 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2947 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2948 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
2950 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2951 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2952 skeleton_t *skeleton;
2953 PRVM_G_INT(OFS_RETURN) = 0;
2954 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2956 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2958 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
2961 // #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)
2962 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
2964 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2965 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2966 skeleton_t *skeleton;
2967 PRVM_G_FLOAT(OFS_RETURN) = 0;
2968 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2970 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2972 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2975 // #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
2976 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
2978 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2979 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2980 skeleton_t *skeleton;
2981 PRVM_G_FLOAT(OFS_RETURN) = 0;
2982 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2984 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2987 // #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)
2988 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
2990 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2991 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2992 skeleton_t *skeleton;
2994 vec3_t forward, left, up, origin;
2995 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2996 VectorClear(PRVM_clientglobalvector(v_forward));
2997 VectorClear(PRVM_clientglobalvector(v_right));
2998 VectorClear(PRVM_clientglobalvector(v_up));
2999 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3001 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3003 matrix = skeleton->relativetransforms[bonenum];
3004 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3005 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3006 VectorNegate(left, PRVM_clientglobalvector(v_right));
3007 VectorCopy(up, PRVM_clientglobalvector(v_up));
3008 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3011 // #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)
3012 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
3014 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3015 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3016 skeleton_t *skeleton;
3019 vec3_t forward, left, up, origin;
3020 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3021 VectorClear(PRVM_clientglobalvector(v_forward));
3022 VectorClear(PRVM_clientglobalvector(v_right));
3023 VectorClear(PRVM_clientglobalvector(v_up));
3024 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3026 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3028 matrix = skeleton->relativetransforms[bonenum];
3029 // convert to absolute
3030 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3033 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3035 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3036 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3037 VectorNegate(left, PRVM_clientglobalvector(v_right));
3038 VectorCopy(up, PRVM_clientglobalvector(v_up));
3039 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3042 // #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)
3043 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3045 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3046 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3047 vec3_t forward, left, up, origin;
3048 skeleton_t *skeleton;
3050 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3052 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3054 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3055 VectorNegate(PRVM_clientglobalvector(v_right), left);
3056 VectorCopy(PRVM_clientglobalvector(v_up), up);
3057 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3058 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3059 skeleton->relativetransforms[bonenum] = matrix;
3062 // #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)
3063 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3065 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3066 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3067 vec3_t forward, left, up, origin;
3068 skeleton_t *skeleton;
3071 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3073 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3075 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3076 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3077 VectorNegate(PRVM_clientglobalvector(v_right), left);
3078 VectorCopy(PRVM_clientglobalvector(v_up), up);
3079 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3080 temp = skeleton->relativetransforms[bonenum];
3081 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3084 // #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)
3085 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3087 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3088 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3089 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3091 vec3_t forward, left, up, origin;
3092 skeleton_t *skeleton;
3095 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3097 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3098 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3099 VectorNegate(PRVM_clientglobalvector(v_right), left);
3100 VectorCopy(PRVM_clientglobalvector(v_up), up);
3101 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3102 firstbone = max(0, firstbone);
3103 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3104 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3106 temp = skeleton->relativetransforms[bonenum];
3107 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3111 // #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
3112 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3114 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3115 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3116 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3117 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3119 skeleton_t *skeletondst;
3120 skeleton_t *skeletonsrc;
3121 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3123 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3125 firstbone = max(0, firstbone);
3126 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3127 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3128 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3129 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3132 // #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)
3133 static void VM_SV_skel_delete(prvm_prog_t *prog)
3135 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3136 skeleton_t *skeleton;
3137 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3140 prog->skeletons[skeletonindex] = NULL;
3143 // #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
3144 static void VM_SV_frameforname(prvm_prog_t *prog)
3146 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3147 dp_model_t *model = SV_GetModelByIndex(modelindex);
3148 const char *name = PRVM_G_STRING(OFS_PARM1);
3150 PRVM_G_FLOAT(OFS_RETURN) = -1;
3151 if (!model || !model->animscenes)
3153 for (i = 0;i < model->numframes;i++)
3155 if (!strcasecmp(model->animscenes[i].name, name))
3157 PRVM_G_FLOAT(OFS_RETURN) = i;
3163 // #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.
3164 static void VM_SV_frameduration(prvm_prog_t *prog)
3166 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3167 dp_model_t *model = SV_GetModelByIndex(modelindex);
3168 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3169 PRVM_G_FLOAT(OFS_RETURN) = 0;
3170 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3172 if (model->animscenes[framenum].framerate)
3173 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3177 prvm_builtin_t vm_sv_builtins[] = {
3178 NULL, // #0 NULL function (not callable) (QUAKE)
3179 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3180 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3181 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3182 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3183 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3184 VM_break, // #6 void() break (QUAKE)
3185 VM_random, // #7 float() random (QUAKE)
3186 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3187 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3188 VM_error, // #10 void(string e) error (QUAKE)
3189 VM_objerror, // #11 void(string e) objerror (QUAKE)
3190 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3191 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3192 VM_spawn, // #14 entity() spawn (QUAKE)
3193 VM_remove, // #15 void(entity e) remove (QUAKE)
3194 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3195 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3196 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3197 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3198 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3199 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3200 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3201 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3202 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3203 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3204 VM_ftos, // #26 string(float f) ftos (QUAKE)
3205 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3206 VM_coredump, // #28 void() coredump (QUAKE)
3207 VM_traceon, // #29 void() traceon (QUAKE)
3208 VM_traceoff, // #30 void() traceoff (QUAKE)
3209 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3210 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3211 NULL, // #33 (QUAKE)
3212 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3213 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3214 VM_rint, // #36 float(float v) rint (QUAKE)
3215 VM_floor, // #37 float(float v) floor (QUAKE)
3216 VM_ceil, // #38 float(float v) ceil (QUAKE)
3217 NULL, // #39 (QUAKE)
3218 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3219 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3220 NULL, // #42 (QUAKE)
3221 VM_fabs, // #43 float(float f) fabs (QUAKE)
3222 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3223 VM_cvar, // #45 float(string s) cvar (QUAKE)
3224 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3225 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3226 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3227 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3228 NULL, // #50 (QUAKE)
3229 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3230 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3231 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3232 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3233 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3234 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3235 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3236 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3237 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3238 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3239 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3240 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3241 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3242 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3243 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3244 NULL, // #66 (QUAKE)
3245 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3246 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3247 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3248 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3249 NULL, // #71 (QUAKE)
3250 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3251 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3252 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3253 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3254 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3255 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3256 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3257 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3258 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3259 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3260 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3261 NULL, // #83 (QUAKE)
3262 NULL, // #84 (QUAKE)
3263 NULL, // #85 (QUAKE)
3264 NULL, // #86 (QUAKE)
3265 NULL, // #87 (QUAKE)
3266 NULL, // #88 (QUAKE)
3267 NULL, // #89 (QUAKE)
3268 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3269 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3270 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3271 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3272 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3273 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3274 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3275 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3276 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3277 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3278 // FrikaC and Telejano range #100-#199
3289 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3290 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3291 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3292 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3293 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3294 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3295 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3296 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3297 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3298 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3379 // FTEQW range #200-#299
3398 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3401 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3402 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3403 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3404 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3405 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3406 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3407 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3408 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3409 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3410 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3412 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3420 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3443 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.
3444 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
3445 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3446 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3447 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)
3448 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
3449 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)
3450 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)
3451 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)
3452 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)
3453 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)
3454 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
3455 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)
3456 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
3457 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.
3480 // CSQC range #300-#399
3481 NULL, // #300 void() clearscene (EXT_CSQC)
3482 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3483 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3484 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3485 NULL, // #304 void() renderscene (EXT_CSQC)
3486 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3487 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3488 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3489 NULL, // #308 void() R_EndPolygon
3491 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3492 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3496 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3497 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3498 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3499 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3500 NULL, // #319 void(string name) freepic (EXT_CSQC)
3501 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3502 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3503 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3504 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3505 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3506 NULL, // #325 void(void) drawresetcliparea
3511 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3512 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3513 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3514 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3515 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3516 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3517 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3518 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3519 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3520 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3521 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3522 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3523 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3524 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3525 NULL, // #344 vector() getmousepos (EXT_CSQC)
3526 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3527 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3528 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3529 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3530 NULL, // #349 float() isdemo (EXT_CSQC)
3531 VM_isserver, // #350 float() isserver (EXT_CSQC)
3532 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3533 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3534 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3535 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3541 NULL, // #360 float() readbyte (EXT_CSQC)
3542 NULL, // #361 float() readchar (EXT_CSQC)
3543 NULL, // #362 float() readshort (EXT_CSQC)
3544 NULL, // #363 float() readlong (EXT_CSQC)
3545 NULL, // #364 float() readcoord (EXT_CSQC)
3546 NULL, // #365 float() readangle (EXT_CSQC)
3547 NULL, // #366 string() readstring (EXT_CSQC)
3548 NULL, // #367 float() readfloat (EXT_CSQC)
3581 // LordHavoc's range #400-#499
3582 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3583 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3584 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3585 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3586 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3587 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3588 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3589 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3590 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)
3591 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3592 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3593 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3594 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3595 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3596 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3597 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3598 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3599 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3600 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3601 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3602 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3603 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3604 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3605 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3606 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3607 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3608 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3609 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3610 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3611 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3612 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3613 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3614 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3615 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3616 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3617 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3618 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3619 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3620 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3621 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3622 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3623 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3624 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3625 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3626 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3627 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3628 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3629 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3630 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3631 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3632 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3633 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3634 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3635 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3636 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3637 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3638 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3639 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3641 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3642 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3643 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3644 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3645 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3646 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3647 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3648 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3649 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3650 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3651 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3653 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3654 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3655 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3656 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3657 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3658 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3659 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3660 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3661 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3662 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3663 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3664 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3665 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3666 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3667 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3668 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3676 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3677 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3678 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3679 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3680 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3681 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3682 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3683 VM_SV_WritePicture, // #501
3685 VM_whichpack, // #503 string(string) whichpack = #503;
3692 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3693 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3694 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3695 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)
3696 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3697 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3698 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3699 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3700 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3701 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3711 VM_loadfromdata, // #529
3712 VM_loadfromfile, // #530
3713 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3715 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3716 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3717 VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP)
3718 VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP)
3719 VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP)
3720 VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP)
3722 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3723 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3724 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3787 VM_callfunction, // #605
3788 VM_writetofile, // #606
3789 VM_isfunction, // #607
3795 VM_parseentitydata, // #613
3806 VM_SV_getextresponse, // #624 string getextresponse(void)
3809 VM_sprintf, // #627 string sprintf(string format, ...)
3810 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3811 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3821 VM_digest_hex, // #639
3825 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3827 void SVVM_init_cmd(prvm_prog_t *prog)
3832 void SVVM_reset_cmd(prvm_prog_t *prog)
3834 World_End(&sv.world);
3835 if(PRVM_serverfunction(SV_Shutdown))
3837 func_t s = PRVM_serverfunction(SV_Shutdown);
3838 PRVM_serverglobalfloat(time) = sv.time;
3839 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3840 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");