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_STRINGCOLORFUNCTIONS "
129 "DP_QC_STRING_CASE_FUNCTIONS "
131 "DP_QC_TOKENIZEBYSEPARATOR "
132 "DP_QC_TOKENIZE_CONSOLE "
135 "DP_QC_TRACE_MOVETYPE_HITMODEL "
136 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
137 "DP_QC_UNLIMITEDTEMPSTRINGS "
141 "DP_QC_VECTOANGLES_WITH_ROLL "
142 "DP_QC_VECTORVECTORS "
149 "DP_SKELETONOBJECTS "
150 "DP_SND_DIRECTIONLESSATTNNONE "
152 "DP_SND_SOUND7_WIP1 "
153 "DP_SND_SOUND7_WIP2 "
157 "DP_SND_GETSOUNDTIME "
159 "DP_VIDEO_SUBTITLES "
163 "DP_SV_BOUNCEFACTOR "
164 "DP_SV_CLIENTCAMERA "
165 "DP_SV_CLIENTCOLORS "
168 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
169 "DP_SV_DISCARDABLEDEMO "
170 "DP_SV_DRAWONLYTOCLIENT "
173 "DP_SV_ENTITYCONTENTSTRANSITION "
174 "DP_SV_MODELFLAGS_AS_EFFECTS "
175 "DP_SV_MOVETYPESTEP_LANDEVENT "
177 "DP_SV_NODRAWTOCLIENT "
178 "DP_SV_ONENTITYNOSPAWNFUNCTION "
179 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
181 "DP_SV_PING_PACKETLOSS "
182 "DP_SV_PLAYERPHYSICS "
184 "DP_SV_POINTPARTICLES "
186 "DP_SV_PRECACHEANYTIME "
190 "DP_SV_ROTATINGBMODEL "
194 "DP_SV_SPAWNFUNC_PREFIX "
195 "DP_SV_WRITEPICTURE "
196 "DP_SV_WRITEUNTERMINATEDSTRING "
200 "DP_TE_EXPLOSIONRGB "
202 "DP_TE_PARTICLECUBE "
203 "DP_TE_PARTICLERAIN "
204 "DP_TE_PARTICLESNOW "
206 "DP_TE_QUADEFFECTS1 "
209 "DP_TE_STANDARDEFFECTBUILTINS "
210 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
214 "FTE_CSQC_SKELETONOBJECTS "
217 "KRIMZON_SV_PARSECLIENTCOMMAND "
220 "NEXUIZ_PLAYERMODEL "
222 "PRYDON_CLIENTCURSOR "
223 "TENEBRAE_GFX_DLIGHTS "
226 //"EXT_CSQC " // not ready yet
233 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.
235 setorigin (entity, origin)
238 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 org = PRVM_G_VECTOR(OFS_PARM1);
257 VectorCopy (org, PRVM_serveredictvector(e, origin));
258 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
259 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
263 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
264 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qboolean rotate)
268 for (i=0 ; i<3 ; i++)
270 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
272 // set derived values
273 VectorCopy (min, PRVM_serveredictvector(e, mins));
274 VectorCopy (max, PRVM_serveredictvector(e, maxs));
275 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
284 the size box is rotated by the current angle
285 LordHavoc: no it isn't...
287 setsize (entity, minvector, maxvector)
290 static void VM_SV_setsize(prvm_prog_t *prog)
295 VM_SAFEPARMCOUNT(3, VM_setsize);
297 e = PRVM_G_EDICT(OFS_PARM0);
298 if (e == prog->edicts)
300 VM_Warning(prog, "setsize: can not modify world entity\n");
303 if (e->priv.server->free)
305 VM_Warning(prog, "setsize: can not modify free entity\n");
308 min = PRVM_G_VECTOR(OFS_PARM1);
309 max = PRVM_G_VECTOR(OFS_PARM2);
310 SetMinMaxSize(prog, e, min, max, false);
318 setmodel(entity, model)
321 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
322 static void VM_SV_setmodel(prvm_prog_t *prog)
328 VM_SAFEPARMCOUNT(2, VM_setmodel);
330 e = PRVM_G_EDICT(OFS_PARM0);
331 if (e == prog->edicts)
333 VM_Warning(prog, "setmodel: can not modify world entity\n");
336 if (e->priv.server->free)
338 VM_Warning(prog, "setmodel: can not modify free entity\n");
341 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
342 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
343 PRVM_serveredictfloat(e, modelindex) = i;
345 mod = SV_GetModelByIndex(i);
349 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
350 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
352 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
355 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
362 single print to a specific client
364 sprint(clientent, value)
367 static void VM_SV_sprint(prvm_prog_t *prog)
371 char string[VM_STRINGTEMP_LENGTH];
373 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
375 VM_VarString(prog, 1, string, sizeof(string));
377 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
378 // LordHavoc: div0 requested that sprintto world operate like print
385 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
387 VM_Warning(prog, "tried to centerprint to a non-client\n");
391 client = svs.clients + entnum-1;
392 if (!client->netconnection)
395 MSG_WriteChar(&client->netconnection->message,svc_print);
396 MSG_WriteString(&client->netconnection->message, string);
404 single print to a specific client
406 centerprint(clientent, value)
409 static void VM_SV_centerprint(prvm_prog_t *prog)
413 char string[VM_STRINGTEMP_LENGTH];
415 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
417 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
419 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
421 VM_Warning(prog, "tried to centerprint to a non-client\n");
425 client = svs.clients + entnum-1;
426 if (!client->netconnection)
429 VM_VarString(prog, 1, string, sizeof(string));
430 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
431 MSG_WriteString(&client->netconnection->message, string);
438 particle(origin, color, count)
441 static void VM_SV_particle(prvm_prog_t *prog)
447 VM_SAFEPARMCOUNT(4, VM_SV_particle);
449 org = PRVM_G_VECTOR(OFS_PARM0);
450 dir = PRVM_G_VECTOR(OFS_PARM1);
451 color = PRVM_G_FLOAT(OFS_PARM2);
452 count = PRVM_G_FLOAT(OFS_PARM3);
453 SV_StartParticle (org, dir, (int)color, (int)count);
463 static void VM_SV_ambientsound(prvm_prog_t *prog)
467 float vol, attenuation;
470 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
472 pos = PRVM_G_VECTOR (OFS_PARM0);
473 samp = PRVM_G_STRING(OFS_PARM1);
474 vol = PRVM_G_FLOAT(OFS_PARM2);
475 attenuation = PRVM_G_FLOAT(OFS_PARM3);
477 // check to see if samp was properly precached
478 soundnum = SV_SoundIndex(samp, 1);
486 // add an svc_spawnambient command to the level signon packet
489 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
491 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
493 MSG_WriteVector(&sv.signon, pos, sv.protocol);
495 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
496 MSG_WriteShort (&sv.signon, soundnum);
498 MSG_WriteByte (&sv.signon, soundnum);
500 MSG_WriteByte (&sv.signon, (int)(vol*255));
501 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
509 Each entity can have eight independant sound sources, like voice,
512 Channel 0 is an auto-allocate channel, the others override anything
513 already running on that entity/channel pair.
515 An attenuation of 0 will play full volume everywhere in the level.
516 Larger attenuations will drop off.
520 static void VM_SV_sound(prvm_prog_t *prog)
524 prvm_edict_t *entity;
530 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
532 entity = PRVM_G_EDICT(OFS_PARM0);
533 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
534 sample = PRVM_G_STRING(OFS_PARM2);
535 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
538 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
542 attenuation = PRVM_G_FLOAT(OFS_PARM4);
546 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
551 if(channel >= 8 && channel <= 15) // weird QW feature
553 flags |= CHANFLAG_RELIABLE;
558 flags = PRVM_G_FLOAT(OFS_PARM6);
560 if (volume < 0 || volume > 255)
562 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
566 if (attenuation < 0 || attenuation > 4)
568 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
572 channel = CHAN_USER2ENGINE(channel);
574 if (!IS_CHAN(channel))
576 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
580 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE, pitchchange);
587 Follows the same logic as VM_SV_sound, except instead of
588 an entity, an origin for the sound is provided, and channel
589 is omitted (since no entity is being tracked).
593 static void VM_SV_pointsound(prvm_prog_t *prog)
601 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
603 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
604 sample = PRVM_G_STRING(OFS_PARM1);
605 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
606 attenuation = PRVM_G_FLOAT(OFS_PARM3);
607 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
609 if (volume < 0 || volume > 255)
611 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
615 if (attenuation < 0 || attenuation > 4)
617 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
621 SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
628 Used for use tracing and shot targeting
629 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
630 if the tryents flag is set.
632 traceline (vector1, vector2, movetype, ignore)
635 static void VM_SV_traceline(prvm_prog_t *prog)
642 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
644 prog->xfunction->builtinsprofile += 30;
646 v1 = PRVM_G_VECTOR(OFS_PARM0);
647 v2 = PRVM_G_VECTOR(OFS_PARM1);
648 move = (int)PRVM_G_FLOAT(OFS_PARM2);
649 ent = PRVM_G_EDICT(OFS_PARM3);
651 if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
652 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));
654 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
656 VM_SetTraceGlobals(prog, &trace);
664 Used for use tracing and shot targeting
665 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
666 if the tryents flag is set.
668 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
671 // LordHavoc: added this for my own use, VERY useful, similar to traceline
672 static void VM_SV_tracebox(prvm_prog_t *prog)
674 float *v1, *v2, *m1, *m2;
679 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
681 prog->xfunction->builtinsprofile += 30;
683 v1 = PRVM_G_VECTOR(OFS_PARM0);
684 m1 = PRVM_G_VECTOR(OFS_PARM1);
685 m2 = PRVM_G_VECTOR(OFS_PARM2);
686 v2 = PRVM_G_VECTOR(OFS_PARM3);
687 move = (int)PRVM_G_FLOAT(OFS_PARM4);
688 ent = PRVM_G_EDICT(OFS_PARM5);
690 if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
691 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));
693 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
695 VM_SetTraceGlobals(prog, &trace);
698 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
703 vec3_t original_origin;
704 vec3_t original_velocity;
705 vec3_t original_angles;
706 vec3_t original_avelocity;
709 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
710 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
711 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
712 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
714 gravity = PRVM_serveredictfloat(tossent, gravity);
717 gravity *= sv_gravity.value * 0.025;
719 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
721 SV_CheckVelocity (tossent);
722 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
723 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
724 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
725 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
726 trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
727 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
728 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
730 if (trace.fraction < 1)
734 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
735 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
736 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
737 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
742 static void VM_SV_tracetoss(prvm_prog_t *prog)
746 prvm_edict_t *ignore;
748 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
750 prog->xfunction->builtinsprofile += 600;
752 ent = PRVM_G_EDICT(OFS_PARM0);
753 if (ent == prog->edicts)
755 VM_Warning(prog, "tracetoss: can not use world entity\n");
758 ignore = PRVM_G_EDICT(OFS_PARM1);
760 trace = SV_Trace_Toss(prog, ent, ignore);
762 VM_SetTraceGlobals(prog, &trace);
765 //============================================================================
767 static int checkpvsbytes;
768 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
770 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
776 // cycle to the next one
778 check = bound(1, check, svs.maxclients);
779 if (check == svs.maxclients)
787 prog->xfunction->builtinsprofile++;
789 if (i == svs.maxclients+1)
791 // look up the client's edict
792 ent = PRVM_EDICT_NUM(i);
793 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
794 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
796 // found a valid client (possibly the same one again)
800 // get the PVS for the entity
801 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
803 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
804 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
813 Returns a client (or object that has a client enemy) that would be a
816 If there is more than one valid option, they are cycled each frame
818 If (self.origin + self.viewofs) is not in the PVS of the current target,
819 it is not returned at all.
824 int c_invis, c_notvis;
825 static void VM_SV_checkclient(prvm_prog_t *prog)
827 prvm_edict_t *ent, *self;
830 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
832 // find a new check if on a new frame
833 if (sv.time - sv.lastchecktime >= 0.1)
835 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
836 sv.lastchecktime = sv.time;
839 // return check if it might be visible
840 ent = PRVM_EDICT_NUM(sv.lastcheck);
841 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
843 VM_RETURN_EDICT(prog->edicts);
847 // if current entity can't possibly see the check entity, return 0
848 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
849 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
850 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
853 VM_RETURN_EDICT(prog->edicts);
857 // might be able to see it
859 VM_RETURN_EDICT(ent);
862 //============================================================================
868 Checks if an entity is in a point's PVS.
869 Should be fast but can be inexact.
871 float checkpvs(vector viewpos, entity viewee) = #240;
874 static void VM_SV_checkpvs(prvm_prog_t *prog)
877 prvm_edict_t *viewee;
882 unsigned char fatpvs[MAX_MAP_LEAFS/8];
885 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
886 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
887 viewee = PRVM_G_EDICT(OFS_PARM1);
889 if(viewee->priv.server->free)
891 VM_Warning(prog, "checkpvs: can not check free entity\n");
892 PRVM_G_FLOAT(OFS_RETURN) = 4;
897 if(!sv.worldmodel || !sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
899 // no PVS support on this worldmodel... darn
900 PRVM_G_FLOAT(OFS_RETURN) = 3;
903 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
906 // viewpos isn't in any PVS... darn
907 PRVM_G_FLOAT(OFS_RETURN) = 2;
910 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
912 // using fat PVS like FTEQW does (slow)
913 if(!sv.worldmodel || !sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
915 // no PVS support on this worldmodel... darn
916 PRVM_G_FLOAT(OFS_RETURN) = 3;
919 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
922 // viewpos isn't in any PVS... darn
923 PRVM_G_FLOAT(OFS_RETURN) = 2;
926 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
935 Sends text over to the client's execution buffer
937 stuffcmd (clientent, value, ...)
940 static void VM_SV_stuffcmd(prvm_prog_t *prog)
944 char string[VM_STRINGTEMP_LENGTH];
946 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
948 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
949 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
951 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
955 VM_VarString(prog, 1, string, sizeof(string));
958 host_client = svs.clients + entnum-1;
959 Host_ClientCommands ("%s", string);
967 Returns a chain of entities that have origins within a spherical area
969 findradius (origin, radius)
972 static void VM_SV_findradius(prvm_prog_t *prog)
974 prvm_edict_t *ent, *chain;
975 vec_t radius, radius2;
976 vec3_t org, eorg, mins, maxs;
979 static prvm_edict_t *touchedicts[MAX_EDICTS];
982 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
985 chainfield = PRVM_G_INT(OFS_PARM2);
987 chainfield = prog->fieldoffsets.chain;
989 prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
991 chain = (prvm_edict_t *)prog->edicts;
993 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
994 radius = PRVM_G_FLOAT(OFS_PARM1);
995 radius2 = radius * radius;
997 mins[0] = org[0] - (radius + 1);
998 mins[1] = org[1] - (radius + 1);
999 mins[2] = org[2] - (radius + 1);
1000 maxs[0] = org[0] + (radius + 1);
1001 maxs[1] = org[1] + (radius + 1);
1002 maxs[2] = org[2] + (radius + 1);
1003 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1004 if (numtouchedicts > MAX_EDICTS)
1006 // this never happens
1007 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1008 numtouchedicts = MAX_EDICTS;
1010 for (i = 0;i < numtouchedicts;i++)
1012 ent = touchedicts[i];
1013 prog->xfunction->builtinsprofile++;
1014 // Quake did not return non-solid entities but darkplaces does
1015 // (note: this is the reason you can't blow up fallen zombies)
1016 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1018 // LordHavoc: compare against bounding box rather than center so it
1019 // doesn't miss large objects, and use DotProduct instead of Length
1020 // for a major speedup
1021 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1022 if (sv_gameplayfix_findradiusdistancetobox.integer)
1024 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1025 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1026 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1029 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1030 if (DotProduct(eorg, eorg) < radius2)
1032 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1037 VM_RETURN_EDICT(chain);
1040 static void VM_SV_precache_sound(prvm_prog_t *prog)
1042 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1043 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1046 static void VM_SV_precache_model(prvm_prog_t *prog)
1048 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1049 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1050 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1057 float(float yaw, float dist[, settrace]) walkmove
1060 static void VM_SV_walkmove(prvm_prog_t *prog)
1069 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1071 // assume failure if it returns early
1072 PRVM_G_FLOAT(OFS_RETURN) = 0;
1074 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1075 if (ent == prog->edicts)
1077 VM_Warning(prog, "walkmove: can not modify world entity\n");
1080 if (ent->priv.server->free)
1082 VM_Warning(prog, "walkmove: can not modify free entity\n");
1085 yaw = PRVM_G_FLOAT(OFS_PARM0);
1086 dist = PRVM_G_FLOAT(OFS_PARM1);
1087 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1089 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1092 yaw = yaw*M_PI*2 / 360;
1094 move[0] = cos(yaw)*dist;
1095 move[1] = sin(yaw)*dist;
1098 // save program state, because SV_movestep may call other progs
1099 oldf = prog->xfunction;
1100 oldself = PRVM_serverglobaledict(self);
1102 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1105 // restore program state
1106 prog->xfunction = oldf;
1107 PRVM_serverglobaledict(self) = oldself;
1118 static void VM_SV_droptofloor(prvm_prog_t *prog)
1124 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1126 // assume failure if it returns early
1127 PRVM_G_FLOAT(OFS_RETURN) = 0;
1129 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1130 if (ent == prog->edicts)
1132 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1135 if (ent->priv.server->free)
1137 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1141 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1144 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1145 if (sv_gameplayfix_unstickentities.integer)
1146 SV_UnstickEntity(ent);
1148 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1149 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1152 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]);
1153 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1154 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1155 VectorSubtract(trace.endpos, offset, trace.endpos);
1156 if (trace.startsolid)
1158 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]);
1159 if (sv_gameplayfix_unstickentities.integer)
1160 SV_UnstickEntity(ent);
1162 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1163 PRVM_serveredictedict(ent, groundentity) = 0;
1164 PRVM_G_FLOAT(OFS_RETURN) = 1;
1166 else if (trace.fraction < 1)
1168 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]);
1169 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1170 if (sv_gameplayfix_unstickentities.integer)
1171 SV_UnstickEntity(ent);
1173 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1174 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1175 PRVM_G_FLOAT(OFS_RETURN) = 1;
1176 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1177 ent->priv.server->suspendedinairflag = true;
1182 if (trace.fraction != 1)
1184 if (trace.fraction < 1)
1185 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1187 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1188 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1189 PRVM_G_FLOAT(OFS_RETURN) = 1;
1190 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1191 ent->priv.server->suspendedinairflag = true;
1200 void(float style, string value) lightstyle
1203 static void VM_SV_lightstyle(prvm_prog_t *prog)
1210 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1212 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1213 val = PRVM_G_STRING(OFS_PARM1);
1215 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1216 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1219 // change the string in sv
1220 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1222 // send message to all clients on this server
1223 if (sv.state != ss_active)
1226 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1228 if (client->active && client->netconnection)
1230 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1231 MSG_WriteChar (&client->netconnection->message,style);
1232 MSG_WriteString (&client->netconnection->message, val);
1242 static void VM_SV_checkbottom(prvm_prog_t *prog)
1244 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1245 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1253 static void VM_SV_pointcontents(prvm_prog_t *prog)
1255 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1256 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1263 Pick a vector for the player to shoot along
1264 vector aim(entity, missilespeed)
1267 static void VM_SV_aim(prvm_prog_t *prog)
1269 prvm_edict_t *ent, *check, *bestent;
1270 vec3_t start, dir, end, bestdir;
1273 float dist, bestdist;
1276 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1278 // assume failure if it returns early
1279 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1280 // if sv_aim is so high it can't possibly accept anything, skip out early
1281 if (sv_aim.value >= 1)
1284 ent = PRVM_G_EDICT(OFS_PARM0);
1285 if (ent == prog->edicts)
1287 VM_Warning(prog, "aim: can not use world entity\n");
1290 if (ent->priv.server->free)
1292 VM_Warning(prog, "aim: can not use free entity\n");
1295 //speed = PRVM_G_FLOAT(OFS_PARM1);
1297 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1300 // try sending a trace straight
1301 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1302 VectorMA (start, 2048, dir, end);
1303 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1304 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1305 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1307 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1312 // try all possible entities
1313 VectorCopy (dir, bestdir);
1314 bestdist = sv_aim.value;
1317 check = PRVM_NEXT_EDICT(prog->edicts);
1318 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1320 prog->xfunction->builtinsprofile++;
1321 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1325 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1326 continue; // don't aim at teammate
1327 for (j=0 ; j<3 ; j++)
1328 end[j] = PRVM_serveredictvector(check, origin)[j]
1329 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1330 VectorSubtract (end, start, dir);
1331 VectorNormalize (dir);
1332 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1333 if (dist < bestdist)
1334 continue; // to far to turn
1335 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1336 if (tr.ent == check)
1337 { // can shoot at this one
1345 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1346 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1347 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1349 VectorNormalize (end);
1350 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1354 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1359 ===============================================================================
1363 ===============================================================================
1366 #define MSG_BROADCAST 0 // unreliable to all
1367 #define MSG_ONE 1 // reliable to one (msg_entity)
1368 #define MSG_ALL 2 // reliable to all
1369 #define MSG_INIT 3 // write to the init string
1370 #define MSG_ENTITY 5
1372 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1378 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1382 return &sv.datagram;
1385 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1386 entnum = PRVM_NUM_FOR_EDICT(ent);
1387 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1389 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1390 return &sv.reliable_datagram;
1393 return &svs.clients[entnum-1].netconnection->message;
1396 VM_Warning(prog, "WriteDest: bad destination\n");
1398 return &sv.reliable_datagram;
1404 return sv.writeentitiestoclient_msg;
1410 static void VM_SV_WriteByte(prvm_prog_t *prog)
1412 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1413 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1416 static void VM_SV_WriteChar(prvm_prog_t *prog)
1418 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1419 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1422 static void VM_SV_WriteShort(prvm_prog_t *prog)
1424 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1425 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1428 static void VM_SV_WriteLong(prvm_prog_t *prog)
1430 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1431 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1434 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1436 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1437 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1440 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1442 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1443 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1446 static void VM_SV_WriteString(prvm_prog_t *prog)
1448 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1449 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1452 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1454 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1455 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1459 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1461 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1462 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1465 // writes a picture as at most size bytes of data
1467 // IMGNAME \0 SIZE(short) IMGDATA
1468 // if failed to read/compress:
1470 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1471 static void VM_SV_WritePicture(prvm_prog_t *prog)
1473 const char *imgname;
1477 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1479 imgname = PRVM_G_STRING(OFS_PARM1);
1480 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1484 MSG_WriteString(WriteDest(prog), imgname);
1485 if(Image_Compress(imgname, size, &buf, &size))
1488 MSG_WriteShort(WriteDest(prog), size);
1489 SZ_Write(WriteDest(prog), (unsigned char *) buf, size);
1494 MSG_WriteShort(WriteDest(prog), 0);
1498 //////////////////////////////////////////////////////////
1500 static void VM_SV_makestatic(prvm_prog_t *prog)
1505 // allow 0 parameters due to an id1 qc bug in which this function is used
1506 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1507 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1509 if (prog->argc >= 1)
1510 ent = PRVM_G_EDICT(OFS_PARM0);
1512 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1513 if (ent == prog->edicts)
1515 VM_Warning(prog, "makestatic: can not modify world entity\n");
1518 if (ent->priv.server->free)
1520 VM_Warning(prog, "makestatic: can not modify free entity\n");
1525 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1530 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1531 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1532 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1534 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1536 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1537 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1538 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1542 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1543 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1544 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1547 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1548 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1549 for (i=0 ; i<3 ; i++)
1551 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1552 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1555 // throw the entity away now
1556 PRVM_ED_Free(prog, ent);
1559 //=============================================================================
1566 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1572 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1574 ent = PRVM_G_EDICT(OFS_PARM0);
1575 i = PRVM_NUM_FOR_EDICT(ent);
1576 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1578 Con_Print("tried to setspawnparms on a non-client\n");
1582 // copy spawn parms out of the client_t
1583 client = svs.clients + i-1;
1584 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1585 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1592 Returns a color vector indicating the lighting at the requested point.
1594 (Internal Operation note: actually measures the light beneath the point, just like
1595 the model lighting on the client)
1600 static void VM_SV_getlight(prvm_prog_t *prog)
1602 vec3_t ambientcolor, diffusecolor, diffusenormal;
1604 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1605 p = PRVM_G_VECTOR(OFS_PARM0);
1606 VectorClear(ambientcolor);
1607 VectorClear(diffusecolor);
1608 VectorClear(diffusenormal);
1609 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1610 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1611 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1616 unsigned char type; // 1/2/8 or other value if isn't used
1620 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1621 static int vm_customstats_last;
1623 void VM_CustomStats_Clear (void)
1627 Z_Free(vm_customstats);
1628 vm_customstats = NULL;
1629 vm_customstats_last = -1;
1633 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1635 prvm_prog_t *prog = SVVM_prog;
1642 for(i=0; i<vm_customstats_last+1 ;i++)
1644 if(!vm_customstats[i].type)
1646 switch(vm_customstats[i].type)
1648 //string as 16 bytes
1651 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1652 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1653 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1654 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1655 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1657 //float field sent as-is
1659 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1661 //integer value of float field
1663 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1671 // void(float index, float type, .void field) SV_AddStat = #232;
1672 // Set up an auto-sent player stat.
1673 // Client's get thier own fields sent to them. Index may not be less than 32.
1674 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1675 // 1: string (4 stats carrying a total of 16 charactures)
1676 // 2: float (one stat, float converted to an integer for transportation)
1677 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1678 static void VM_SV_AddStat(prvm_prog_t *prog)
1683 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1687 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1690 VM_Warning(prog, "PF_SV_AddStat: not enough memory\n");
1694 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1695 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1696 off = PRVM_G_INT (OFS_PARM2);
1701 VM_Warning(prog, "PF_SV_AddStat: index may not be less than 32\n");
1704 if(i >= (MAX_CL_STATS-32))
1706 VM_Warning(prog, "PF_SV_AddStat: index >= MAX_CL_STATS\n");
1709 if(i > (MAX_CL_STATS-32-4) && type == 1)
1711 VM_Warning(prog, "PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1714 vm_customstats[i].type = type;
1715 vm_customstats[i].fieldoffset = off;
1716 if(vm_customstats_last < i)
1717 vm_customstats_last = i;
1724 copies data from one entity to another
1726 copyentity(src, dst)
1729 static void VM_SV_copyentity(prvm_prog_t *prog)
1731 prvm_edict_t *in, *out;
1732 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1733 in = PRVM_G_EDICT(OFS_PARM0);
1734 if (in == prog->edicts)
1736 VM_Warning(prog, "copyentity: can not read world entity\n");
1739 if (in->priv.server->free)
1741 VM_Warning(prog, "copyentity: can not read free entity\n");
1744 out = PRVM_G_EDICT(OFS_PARM1);
1745 if (out == prog->edicts)
1747 VM_Warning(prog, "copyentity: can not modify world entity\n");
1750 if (out->priv.server->free)
1752 VM_Warning(prog, "copyentity: can not modify free entity\n");
1755 memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
1764 sets the color of a client and broadcasts the update to all connected clients
1766 setcolor(clientent, value)
1769 static void VM_SV_setcolor(prvm_prog_t *prog)
1774 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1775 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1776 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1778 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1780 Con_Print("tried to setcolor a non-client\n");
1784 client = svs.clients + entnum-1;
1787 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1788 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1791 if (client->old_colors != client->colors)
1793 client->old_colors = client->colors;
1794 // send notification to all clients
1795 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1796 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1797 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1805 effect(origin, modelname, startframe, framecount, framerate)
1808 static void VM_SV_effect(prvm_prog_t *prog)
1812 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1813 s = PRVM_G_STRING(OFS_PARM1);
1816 VM_Warning(prog, "effect: no model specified\n");
1820 i = SV_ModelIndex(s, 1);
1823 VM_Warning(prog, "effect: model not precached\n");
1827 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1829 VM_Warning(prog, "effect: framecount < 1\n");
1833 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1835 VM_Warning(prog, "effect: framerate < 1\n");
1839 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1842 static void VM_SV_te_blood(prvm_prog_t *prog)
1844 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1845 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1847 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1848 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1850 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1851 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1852 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1854 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1855 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1856 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1858 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1859 SV_FlushBroadcastMessages();
1862 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1864 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1865 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1867 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1868 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1870 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1874 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1875 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1876 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1878 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1880 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1881 SV_FlushBroadcastMessages();
1884 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1886 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1887 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1888 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1890 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1891 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1892 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1894 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1895 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1896 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1897 SV_FlushBroadcastMessages();
1900 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1902 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1903 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1905 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1906 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1912 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1913 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1914 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1916 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1917 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1918 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1920 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1922 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1923 // gravity true/false
1924 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1926 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1927 SV_FlushBroadcastMessages();
1930 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1932 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1933 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1935 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1936 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1942 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1943 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1944 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1948 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1950 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1952 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1953 SV_FlushBroadcastMessages();
1956 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1958 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1959 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1961 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1962 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1964 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1965 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1970 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1972 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1973 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1974 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1976 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1978 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1979 SV_FlushBroadcastMessages();
1982 static void VM_SV_te_spark(prvm_prog_t *prog)
1984 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1985 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1987 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1988 MSG_WriteByte(&sv.datagram, TE_SPARK);
1990 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1991 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1992 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1994 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1995 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1996 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1998 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1999 SV_FlushBroadcastMessages();
2002 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2004 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2005 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2006 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2008 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2009 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2010 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2011 SV_FlushBroadcastMessages();
2014 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2016 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2017 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2018 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2020 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2021 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2022 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2023 SV_FlushBroadcastMessages();
2026 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2028 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2029 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2030 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2032 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2033 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2034 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2035 SV_FlushBroadcastMessages();
2038 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2040 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2041 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2042 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2044 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2045 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2046 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2047 SV_FlushBroadcastMessages();
2050 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2052 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2053 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2054 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2056 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2058 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2059 SV_FlushBroadcastMessages();
2062 static void VM_SV_te_customflash(prvm_prog_t *prog)
2064 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2065 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2067 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2068 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2070 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2071 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2072 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2074 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2076 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2078 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2079 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2080 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2081 SV_FlushBroadcastMessages();
2084 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2086 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2087 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2088 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2090 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2091 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2092 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2093 SV_FlushBroadcastMessages();
2096 static void VM_SV_te_spike(prvm_prog_t *prog)
2098 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2099 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2100 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2102 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2103 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2104 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2105 SV_FlushBroadcastMessages();
2108 static void VM_SV_te_superspike(prvm_prog_t *prog)
2110 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2111 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2112 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2114 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2115 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2116 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2117 SV_FlushBroadcastMessages();
2120 static void VM_SV_te_explosion(prvm_prog_t *prog)
2122 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2123 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2124 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2126 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2127 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2128 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2129 SV_FlushBroadcastMessages();
2132 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2134 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2135 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2136 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2138 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2139 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2140 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2141 SV_FlushBroadcastMessages();
2144 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2146 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2147 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2148 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2150 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2151 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2152 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2153 SV_FlushBroadcastMessages();
2156 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2158 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2159 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2160 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2162 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2163 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2164 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2165 SV_FlushBroadcastMessages();
2168 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2170 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2171 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2172 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2174 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2175 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2176 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2177 SV_FlushBroadcastMessages();
2180 static void VM_SV_te_teleport(prvm_prog_t *prog)
2182 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2183 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2184 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2186 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2187 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2188 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2189 SV_FlushBroadcastMessages();
2192 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2194 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2195 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2196 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2198 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2199 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2200 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2202 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2203 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2204 SV_FlushBroadcastMessages();
2207 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2209 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2210 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2211 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2213 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2215 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2216 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2217 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2219 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2220 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2221 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2222 SV_FlushBroadcastMessages();
2225 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2227 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2228 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2229 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2231 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2234 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2235 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2237 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2238 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2239 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2240 SV_FlushBroadcastMessages();
2243 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2245 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2246 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2247 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2249 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2251 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2252 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2253 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2255 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2256 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2257 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2258 SV_FlushBroadcastMessages();
2261 static void VM_SV_te_beam(prvm_prog_t *prog)
2263 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2264 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2265 MSG_WriteByte(&sv.datagram, TE_BEAM);
2267 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2269 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2270 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2271 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2273 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2274 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2275 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2276 SV_FlushBroadcastMessages();
2279 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2281 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2282 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2283 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2284 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2285 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2286 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2287 SV_FlushBroadcastMessages();
2290 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2292 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2293 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2294 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2296 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2297 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2298 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2300 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2301 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2302 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2304 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2305 SV_FlushBroadcastMessages();
2308 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2309 //this function originally written by KrimZon, made shorter by LordHavoc
2310 static void VM_SV_clientcommand(prvm_prog_t *prog)
2312 client_t *temp_client;
2314 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2316 //find client for this entity
2317 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2318 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2320 Con_Print("PF_clientcommand: entity is not a client\n");
2324 temp_client = host_client;
2325 host_client = svs.clients + i;
2326 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
2327 host_client = temp_client;
2330 //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)
2331 static void VM_SV_setattachment(prvm_prog_t *prog)
2333 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2334 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2335 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2338 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2340 if (e == prog->edicts)
2342 VM_Warning(prog, "setattachment: can not modify world entity\n");
2345 if (e->priv.server->free)
2347 VM_Warning(prog, "setattachment: can not modify free entity\n");
2351 if (tagentity == NULL)
2352 tagentity = prog->edicts;
2356 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2358 model = SV_GetModelFromEdict(tagentity);
2361 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2363 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);
2366 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));
2369 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2370 PRVM_serveredictfloat(e, tag_index) = tagindex;
2373 /////////////////////////////////////////
2374 // DP_MD3_TAGINFO extension coded by VorteX
2376 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2380 i = (int)PRVM_serveredictfloat(e, modelindex);
2381 if (i < 1 || i >= MAX_MODELS)
2384 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2387 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2394 Matrix4x4_CreateIdentity(tag_localmatrix);
2396 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2398 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2409 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2412 float pitchsign = 1;
2414 scale = PRVM_serveredictfloat(ent, scale);
2419 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);
2422 pitchsign = SV_GetPitchSign(prog, ent);
2423 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);
2427 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2430 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2432 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2433 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2434 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2435 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2437 *out = identitymatrix;
2441 // Warnings/errors code:
2442 // 0 - normal (everything all-right)
2445 // 3 - null or non-precached model
2446 // 4 - no tags with requested index
2447 // 5 - runaway loop at attachment chain
2448 extern cvar_t cl_bob;
2449 extern cvar_t cl_bobcycle;
2450 extern cvar_t cl_bobup;
2451 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2454 int modelindex, attachloop;
2455 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2458 *out = identitymatrix; // warnings and errors return identical matrix
2460 if (ent == prog->edicts)
2462 if (ent->priv.server->free)
2465 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2466 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2469 model = SV_GetModelByIndex(modelindex);
2471 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2472 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2473 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2475 tagmatrix = identitymatrix;
2476 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2480 if (attachloop >= 256) // prevent runaway looping
2482 // apply transformation by child's tagindex on parent entity and then
2483 // by parent entity itself
2484 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2485 if (ret && attachloop == 0)
2487 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2488 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2489 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2490 // next iteration we process the parent entity
2491 if (PRVM_serveredictedict(ent, tag_entity))
2493 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2494 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2501 // RENDER_VIEWMODEL magic
2502 if (PRVM_serveredictedict(ent, viewmodelforclient))
2504 Matrix4x4_Copy(&tagmatrix, out);
2505 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2507 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2508 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2511 // Cl_bob, ported from rendering code
2512 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2515 // LordHavoc: this code is *weird*, but not replacable (I think it
2516 // should be done in QC on the server, but oh well, quake is quake)
2517 // LordHavoc: figured out bobup: the time at which the sin is at 180
2518 // degrees (which allows lengthening or squishing the peak or valley)
2519 cycle = sv.time/cl_bobcycle.value;
2520 cycle -= (int)cycle;
2521 if (cycle < cl_bobup.value)
2522 cycle = sin(M_PI * cycle / cl_bobup.value);
2524 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2525 // bob is proportional to velocity in the xy plane
2526 // (don't count Z, or jumping messes it up)
2527 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;
2528 bob = bob*0.3 + bob*0.7*cycle;
2529 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2536 //float(entity ent, string tagname) gettagindex;
2538 static void VM_SV_gettagindex(prvm_prog_t *prog)
2541 const char *tag_name;
2544 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2546 ent = PRVM_G_EDICT(OFS_PARM0);
2547 tag_name = PRVM_G_STRING(OFS_PARM1);
2549 if (ent == prog->edicts)
2551 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2554 if (ent->priv.server->free)
2556 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2561 if (!SV_GetModelFromEdict(ent))
2562 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2565 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2567 if(developer_extra.integer)
2568 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2570 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2573 //vector(entity ent, float tagindex) gettaginfo;
2574 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2578 matrix4x4_t tag_matrix;
2579 matrix4x4_t tag_localmatrix;
2581 const char *tagname;
2583 vec3_t fo, le, up, trans;
2584 const dp_model_t *model;
2586 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2588 e = PRVM_G_EDICT(OFS_PARM0);
2589 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2591 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2592 Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
2593 VectorScale(le, -1, PRVM_serverglobalvector(v_right));
2594 model = SV_GetModelFromEdict(e);
2595 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2596 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2597 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2598 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2599 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2601 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2602 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2603 VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
2604 VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
2605 VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
2606 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2611 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2614 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2617 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2620 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2623 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2628 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2629 static void VM_SV_dropclient(prvm_prog_t *prog)
2632 client_t *oldhostclient;
2633 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2634 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2635 if (clientnum < 0 || clientnum >= svs.maxclients)
2637 VM_Warning(prog, "dropclient: not a client\n");
2640 if (!svs.clients[clientnum].active)
2642 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2645 oldhostclient = host_client;
2646 host_client = svs.clients + clientnum;
2647 SV_DropClient(false);
2648 host_client = oldhostclient;
2651 //entity() spawnclient (DP_SV_BOTCLIENT)
2652 static void VM_SV_spawnclient(prvm_prog_t *prog)
2656 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2657 prog->xfunction->builtinsprofile += 2;
2659 for (i = 0;i < svs.maxclients;i++)
2661 if (!svs.clients[i].active)
2663 prog->xfunction->builtinsprofile += 100;
2664 SV_ConnectClient (i, NULL);
2665 // this has to be set or else ClientDisconnect won't be called
2666 // we assume the qc will call ClientConnect...
2667 svs.clients[i].clientconnectcalled = true;
2668 ed = PRVM_EDICT_NUM(i + 1);
2672 VM_RETURN_EDICT(ed);
2675 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2676 static void VM_SV_clienttype(prvm_prog_t *prog)
2679 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2680 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2681 if (clientnum < 0 || clientnum >= svs.maxclients)
2682 PRVM_G_FLOAT(OFS_RETURN) = 3;
2683 else if (!svs.clients[clientnum].active)
2684 PRVM_G_FLOAT(OFS_RETURN) = 0;
2685 else if (svs.clients[clientnum].netconnection)
2686 PRVM_G_FLOAT(OFS_RETURN) = 1;
2688 PRVM_G_FLOAT(OFS_RETURN) = 2;
2695 string(string key) serverkey
2698 static void VM_SV_serverkey(prvm_prog_t *prog)
2700 char string[VM_STRINGTEMP_LENGTH];
2701 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2702 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2703 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2706 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2707 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2712 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2714 e = PRVM_G_EDICT(OFS_PARM0);
2715 if (e == prog->edicts)
2717 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2720 if (e->priv.server->free)
2722 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2725 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2726 if (i <= 0 || i >= MAX_MODELS)
2728 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2731 if (!sv.model_precache[i][0])
2733 VM_Warning(prog, "setmodelindex: model not precached\n");
2737 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2738 PRVM_serveredictfloat(e, modelindex) = i;
2740 mod = SV_GetModelByIndex(i);
2744 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2745 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2747 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2750 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2753 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2754 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2757 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2759 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2761 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2762 if (i <= 0 || i >= MAX_MODELS)
2764 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2767 if (!sv.model_precache[i][0])
2769 VM_Warning(prog, "modelnameforindex: model not precached\n");
2773 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2776 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2777 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2780 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2781 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2784 PRVM_G_FLOAT(OFS_RETURN) = i;
2787 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2788 static void VM_SV_trailparticles(prvm_prog_t *prog)
2790 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2792 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2795 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2796 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2797 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2798 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2799 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2800 SV_FlushBroadcastMessages();
2803 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2804 static void VM_SV_pointparticles(prvm_prog_t *prog)
2806 int effectnum, count;
2808 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2810 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2813 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2814 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2815 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2816 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2817 if (count == 1 && !VectorLength2(vel))
2820 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2821 MSG_WriteShort(&sv.datagram, effectnum);
2822 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2826 // 1+2+12+12+2=29 bytes
2827 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2828 MSG_WriteShort(&sv.datagram, effectnum);
2829 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2830 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2831 MSG_WriteShort(&sv.datagram, count);
2834 SV_FlushBroadcastMessages();
2837 //PF_setpause, // void(float pause) setpause = #531;
2838 static void VM_SV_setpause(prvm_prog_t *prog) {
2840 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2841 if (pauseValue != 0) { //pause the game
2843 sv.pausedstart = realtime;
2844 } else { //disable pause, in case it was enabled
2845 if (sv.paused != 0) {
2850 // send notification to all clients
2851 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2852 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2855 // #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.
2856 static void VM_SV_skel_create(prvm_prog_t *prog)
2858 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2859 dp_model_t *model = SV_GetModelByIndex(modelindex);
2860 skeleton_t *skeleton;
2862 PRVM_G_FLOAT(OFS_RETURN) = 0;
2863 if (!model || !model->num_bones)
2865 for (i = 0;i < MAX_EDICTS;i++)
2866 if (!prog->skeletons[i])
2868 if (i == MAX_EDICTS)
2870 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(prog->progs_mempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2871 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2872 skeleton->model = model;
2873 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2874 // initialize to identity matrices
2875 for (i = 0;i < skeleton->model->num_bones;i++)
2876 skeleton->relativetransforms[i] = identitymatrix;
2879 // #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
2880 static void VM_SV_skel_build(prvm_prog_t *prog)
2882 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2883 skeleton_t *skeleton;
2884 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2885 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2886 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2887 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2888 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2889 dp_model_t *model = SV_GetModelByIndex(modelindex);
2894 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2895 frameblend_t frameblend[MAX_FRAMEBLENDS];
2896 matrix4x4_t blendedmatrix;
2898 PRVM_G_FLOAT(OFS_RETURN) = 0;
2899 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2901 firstbone = max(0, firstbone);
2902 lastbone = min(lastbone, model->num_bones - 1);
2903 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2904 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2905 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time);
2906 blendfrac = 1.0f - retainfrac;
2907 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2908 frameblend[numblends].lerp *= blendfrac;
2909 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2911 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2912 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2913 for (blendindex = 0;blendindex < numblends;blendindex++)
2915 Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2916 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2918 skeleton->relativetransforms[bonenum] = blendedmatrix;
2920 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2923 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2924 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
2926 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2927 skeleton_t *skeleton;
2928 PRVM_G_FLOAT(OFS_RETURN) = 0;
2929 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2931 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2934 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2935 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
2937 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2938 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2939 skeleton_t *skeleton;
2940 PRVM_G_INT(OFS_RETURN) = 0;
2941 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2943 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2945 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
2948 // #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)
2949 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
2951 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2952 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2953 skeleton_t *skeleton;
2954 PRVM_G_FLOAT(OFS_RETURN) = 0;
2955 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2957 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2959 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2962 // #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
2963 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
2965 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2966 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2967 skeleton_t *skeleton;
2968 PRVM_G_FLOAT(OFS_RETURN) = 0;
2969 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2971 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2974 // #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)
2975 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
2977 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2978 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2979 skeleton_t *skeleton;
2981 vec3_t forward, left, up, origin;
2982 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2983 VectorClear(PRVM_clientglobalvector(v_forward));
2984 VectorClear(PRVM_clientglobalvector(v_right));
2985 VectorClear(PRVM_clientglobalvector(v_up));
2986 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2988 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2990 matrix = skeleton->relativetransforms[bonenum];
2991 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2992 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2993 VectorNegate(left, PRVM_clientglobalvector(v_right));
2994 VectorCopy(up, PRVM_clientglobalvector(v_up));
2995 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2998 // #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)
2999 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
3001 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3002 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3003 skeleton_t *skeleton;
3006 vec3_t forward, left, up, origin;
3007 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3008 VectorClear(PRVM_clientglobalvector(v_forward));
3009 VectorClear(PRVM_clientglobalvector(v_right));
3010 VectorClear(PRVM_clientglobalvector(v_up));
3011 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3013 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3015 matrix = skeleton->relativetransforms[bonenum];
3016 // convert to absolute
3017 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3020 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3022 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3023 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3024 VectorNegate(left, PRVM_clientglobalvector(v_right));
3025 VectorCopy(up, PRVM_clientglobalvector(v_up));
3026 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3029 // #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)
3030 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3032 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3033 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3034 vec3_t forward, left, up, origin;
3035 skeleton_t *skeleton;
3037 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3039 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3041 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3042 VectorNegate(PRVM_clientglobalvector(v_right), left);
3043 VectorCopy(PRVM_clientglobalvector(v_up), up);
3044 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3045 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3046 skeleton->relativetransforms[bonenum] = matrix;
3049 // #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)
3050 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3052 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3053 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3054 vec3_t forward, left, up, origin;
3055 skeleton_t *skeleton;
3058 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3060 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3062 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3063 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3064 VectorNegate(PRVM_clientglobalvector(v_right), left);
3065 VectorCopy(PRVM_clientglobalvector(v_up), up);
3066 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3067 temp = skeleton->relativetransforms[bonenum];
3068 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3071 // #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)
3072 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3074 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3075 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3076 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3078 vec3_t forward, left, up, origin;
3079 skeleton_t *skeleton;
3082 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3084 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3085 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3086 VectorNegate(PRVM_clientglobalvector(v_right), left);
3087 VectorCopy(PRVM_clientglobalvector(v_up), up);
3088 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3089 firstbone = max(0, firstbone);
3090 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3091 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3093 temp = skeleton->relativetransforms[bonenum];
3094 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3098 // #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
3099 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3101 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3102 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3103 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3104 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3106 skeleton_t *skeletondst;
3107 skeleton_t *skeletonsrc;
3108 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3110 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3112 firstbone = max(0, firstbone);
3113 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3114 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3115 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3116 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3119 // #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)
3120 static void VM_SV_skel_delete(prvm_prog_t *prog)
3122 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3123 skeleton_t *skeleton;
3124 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3127 prog->skeletons[skeletonindex] = NULL;
3130 // #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
3131 static void VM_SV_frameforname(prvm_prog_t *prog)
3133 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3134 dp_model_t *model = SV_GetModelByIndex(modelindex);
3135 const char *name = PRVM_G_STRING(OFS_PARM1);
3137 PRVM_G_FLOAT(OFS_RETURN) = -1;
3138 if (!model || !model->animscenes)
3140 for (i = 0;i < model->numframes;i++)
3142 if (!strcasecmp(model->animscenes[i].name, name))
3144 PRVM_G_FLOAT(OFS_RETURN) = i;
3150 // #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.
3151 static void VM_SV_frameduration(prvm_prog_t *prog)
3153 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3154 dp_model_t *model = SV_GetModelByIndex(modelindex);
3155 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3156 PRVM_G_FLOAT(OFS_RETURN) = 0;
3157 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3159 if (model->animscenes[framenum].framerate)
3160 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3164 prvm_builtin_t vm_sv_builtins[] = {
3165 NULL, // #0 NULL function (not callable) (QUAKE)
3166 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3167 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3168 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3169 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3170 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3171 VM_break, // #6 void() break (QUAKE)
3172 VM_random, // #7 float() random (QUAKE)
3173 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3174 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3175 VM_error, // #10 void(string e) error (QUAKE)
3176 VM_objerror, // #11 void(string e) objerror (QUAKE)
3177 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3178 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3179 VM_spawn, // #14 entity() spawn (QUAKE)
3180 VM_remove, // #15 void(entity e) remove (QUAKE)
3181 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3182 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3183 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3184 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3185 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3186 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3187 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3188 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3189 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3190 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3191 VM_ftos, // #26 string(float f) ftos (QUAKE)
3192 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3193 VM_coredump, // #28 void() coredump (QUAKE)
3194 VM_traceon, // #29 void() traceon (QUAKE)
3195 VM_traceoff, // #30 void() traceoff (QUAKE)
3196 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3197 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3198 NULL, // #33 (QUAKE)
3199 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3200 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3201 VM_rint, // #36 float(float v) rint (QUAKE)
3202 VM_floor, // #37 float(float v) floor (QUAKE)
3203 VM_ceil, // #38 float(float v) ceil (QUAKE)
3204 NULL, // #39 (QUAKE)
3205 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3206 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3207 NULL, // #42 (QUAKE)
3208 VM_fabs, // #43 float(float f) fabs (QUAKE)
3209 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3210 VM_cvar, // #45 float(string s) cvar (QUAKE)
3211 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3212 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3213 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3214 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3215 NULL, // #50 (QUAKE)
3216 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3217 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3218 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3219 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3220 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3221 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3222 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3223 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3224 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3225 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3226 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3227 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3228 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3229 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3230 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3231 NULL, // #66 (QUAKE)
3232 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3233 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3234 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3235 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3236 NULL, // #71 (QUAKE)
3237 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3238 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3239 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3240 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3241 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3242 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3243 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3244 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3245 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3246 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3247 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3248 NULL, // #83 (QUAKE)
3249 NULL, // #84 (QUAKE)
3250 NULL, // #85 (QUAKE)
3251 NULL, // #86 (QUAKE)
3252 NULL, // #87 (QUAKE)
3253 NULL, // #88 (QUAKE)
3254 NULL, // #89 (QUAKE)
3255 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3256 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3257 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3258 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3259 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3260 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3261 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3262 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3263 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3264 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3265 // FrikaC and Telejano range #100-#199
3276 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3277 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3278 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3279 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3280 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3281 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3282 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3283 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3284 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3285 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3366 // FTEQW range #200-#299
3385 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3388 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3389 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3390 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3391 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3392 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3393 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3394 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3395 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3396 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3397 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3399 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3407 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3430 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.
3431 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
3432 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3433 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3434 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)
3435 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
3436 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)
3437 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)
3438 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)
3439 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)
3440 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)
3441 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
3442 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)
3443 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
3444 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.
3467 // CSQC range #300-#399
3468 NULL, // #300 void() clearscene (EXT_CSQC)
3469 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3470 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3471 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3472 NULL, // #304 void() renderscene (EXT_CSQC)
3473 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3474 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3475 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3476 NULL, // #308 void() R_EndPolygon
3478 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3479 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3483 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3484 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3485 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3486 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3487 NULL, // #319 void(string name) freepic (EXT_CSQC)
3488 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3489 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3490 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3491 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3492 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3493 NULL, // #325 void(void) drawresetcliparea
3498 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3499 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3500 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3501 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3502 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3503 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3504 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3505 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3506 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3507 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3508 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3509 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3510 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3511 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3512 NULL, // #344 vector() getmousepos (EXT_CSQC)
3513 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3514 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3515 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3516 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3517 NULL, // #349 float() isdemo (EXT_CSQC)
3518 VM_isserver, // #350 float() isserver (EXT_CSQC)
3519 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3520 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3521 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3522 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3528 NULL, // #360 float() readbyte (EXT_CSQC)
3529 NULL, // #361 float() readchar (EXT_CSQC)
3530 NULL, // #362 float() readshort (EXT_CSQC)
3531 NULL, // #363 float() readlong (EXT_CSQC)
3532 NULL, // #364 float() readcoord (EXT_CSQC)
3533 NULL, // #365 float() readangle (EXT_CSQC)
3534 NULL, // #366 string() readstring (EXT_CSQC)
3535 NULL, // #367 float() readfloat (EXT_CSQC)
3568 // LordHavoc's range #400-#499
3569 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3570 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3571 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3572 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3573 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3574 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3575 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3576 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3577 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)
3578 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3579 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3580 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3581 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3582 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3583 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3584 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3585 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3586 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3587 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3588 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3589 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3590 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3591 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3592 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3593 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3594 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3595 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3596 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3597 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3598 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3599 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3600 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3601 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3602 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3603 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3604 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3605 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3606 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3607 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3608 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3609 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3610 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3611 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3612 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3613 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3614 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3615 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3616 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3617 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3618 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3619 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3620 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3621 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3622 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3623 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3624 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3625 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3626 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3628 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3629 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3630 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3631 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3632 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3633 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3634 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3635 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3636 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3637 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3638 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3640 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3641 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3642 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3643 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3644 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3645 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3646 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3647 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3648 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3649 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3650 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3651 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3652 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3653 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3654 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3655 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3663 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3664 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3665 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3666 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3667 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3668 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3669 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3670 VM_SV_WritePicture, // #501
3672 VM_whichpack, // #503 string(string) whichpack = #503;
3679 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3680 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3681 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3682 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)
3683 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3684 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3685 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3686 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3687 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3688 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3698 VM_loadfromdata, // #529
3699 VM_loadfromfile, // #530
3700 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3702 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3703 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3709 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3710 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3711 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3774 VM_callfunction, // #605
3775 VM_writetofile, // #606
3776 VM_isfunction, // #607
3782 VM_parseentitydata, // #613
3793 VM_SV_getextresponse, // #624 string getextresponse(void)
3796 VM_sprintf, // #627 string sprintf(string format, ...)
3797 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3798 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3808 VM_digest_hex, // #639
3812 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3814 void SVVM_init_cmd(prvm_prog_t *prog)
3819 void SVVM_reset_cmd(prvm_prog_t *prog)
3821 World_End(&sv.world);
3822 if(PRVM_serverfunction(SV_Shutdown))
3824 func_t s = PRVM_serverfunction(SV_Shutdown);
3825 PRVM_serverglobalfloat(time) = sv.time;
3826 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3827 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");