6 //============================================================================
11 const char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
24 "DP_CSQC_ENTITYWORLDOBJECT "
25 "DP_CSQC_ENTITYMODELLIGHT "
26 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
28 "DP_CSQC_MINFPS_QUALITY "
29 "DP_CSQC_MULTIFRAME_INTERPOLATION "
30 "DP_CSQC_BOXPARTICLES "
31 "DP_CSQC_SPAWNPARTICLE "
32 "DP_CSQC_QUERYRENDERENTITY "
33 "DP_CSQC_ROTATEMOVES "
35 "DP_CSQC_V_CALCREFDEF_WIP1 "
36 "DP_CSQC_V_CALCREFDEF_WIP2 "
40 "DP_EF_DYNAMICMODELLIGHT "
49 "DP_EF_RESTARTANIM_BIT "
54 "DP_ENT_CUSTOMCOLORMAP "
55 "DP_ENT_EXTERIORMODELTOCLIENT "
58 "DP_ENT_LOWPRECISION "
60 "DP_ENT_TRAILEFFECTNUM "
62 "DP_GFX_EXTERNALTEXTURES "
63 "DP_GFX_EXTERNALTEXTURES_PERMAP "
65 "DP_GFX_MODEL_INTERPOLATION "
66 "DP_GFX_QUAKE3MODELTAGS "
70 "DP_GFX_FONTS_FREETYPE "
72 "DP_FONT_VARIABLEWIDTH "
74 "DP_HALFLIFE_MAP_CVAR "
77 "DP_LIGHTSTYLE_STATICVALUE "
81 "DP_MOVETYPEBOUNCEMISSILE "
82 "DP_MOVETYPEFLYWORLDONLY "
85 "DP_QC_ASINACOSATANATAN2TAN "
91 "DP_QC_CVAR_DEFSTRING "
92 "DP_QC_CVAR_DESCRIPTION "
96 "DP_QC_DIGEST_SHA256 "
101 "DP_QC_EXTRESPONSEPACKET "
103 "DP_QC_FINDCHAINFLAGS "
104 "DP_QC_FINDCHAINFLOAT "
105 "DP_QC_FINDCHAIN_TOFIELD "
111 "DP_QC_GETSURFACETRIANGLE "
112 "DP_QC_GETSURFACEPOINTATTRIBUTE "
114 "DP_QC_GETTAGINFO_BONEPROPERTIES "
116 "DP_QC_GETTIME_CDTRACK "
120 "DP_QC_MULTIPLETEMPSTRINGS "
121 "DP_QC_NUM_FOR_EDICT "
123 "DP_QC_SINCOSSQRTPOW "
126 "DP_QC_STRINGBUFFERS "
127 "DP_QC_STRINGBUFFERS_CVARLIST "
128 "DP_QC_STRINGBUFFERS_EXT_WIP "
129 "DP_QC_STRINGCOLORFUNCTIONS "
130 "DP_QC_STRING_CASE_FUNCTIONS "
132 "DP_QC_TOKENIZEBYSEPARATOR "
133 "DP_QC_TOKENIZE_CONSOLE "
136 "DP_QC_TRACE_MOVETYPE_HITMODEL "
137 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
138 "DP_QC_UNLIMITEDTEMPSTRINGS "
142 "DP_QC_VECTOANGLES_WITH_ROLL "
143 "DP_QC_VECTORVECTORS "
150 "DP_SKELETONOBJECTS "
151 "DP_SND_DIRECTIONLESSATTNNONE "
153 "DP_SND_SOUND7_WIP1 "
154 "DP_SND_SOUND7_WIP2 "
158 "DP_SND_GETSOUNDTIME "
160 "DP_VIDEO_SUBTITLES "
164 "DP_SV_BOUNCEFACTOR "
165 "DP_SV_CLIENTCAMERA "
166 "DP_SV_CLIENTCOLORS "
169 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
170 "DP_SV_DISCARDABLEDEMO "
171 "DP_SV_DRAWONLYTOCLIENT "
174 "DP_SV_ENTITYCONTENTSTRANSITION "
175 "DP_SV_MODELFLAGS_AS_EFFECTS "
176 "DP_SV_MOVETYPESTEP_LANDEVENT "
178 "DP_SV_NODRAWTOCLIENT "
179 "DP_SV_ONENTITYNOSPAWNFUNCTION "
180 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
182 "DP_SV_PING_PACKETLOSS "
183 "DP_SV_PLAYERPHYSICS "
185 "DP_SV_POINTPARTICLES "
187 "DP_SV_PRECACHEANYTIME "
191 "DP_SV_ROTATINGBMODEL "
195 "DP_SV_SPAWNFUNC_PREFIX "
196 "DP_SV_WRITEPICTURE "
197 "DP_SV_WRITEUNTERMINATEDSTRING "
201 "DP_TE_EXPLOSIONRGB "
203 "DP_TE_PARTICLECUBE "
204 "DP_TE_PARTICLERAIN "
205 "DP_TE_PARTICLESNOW "
207 "DP_TE_QUADEFFECTS1 "
210 "DP_TE_STANDARDEFFECTBUILTINS "
211 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
215 "FTE_CSQC_SKELETONOBJECTS "
218 "KRIMZON_SV_PARSECLIENTCOMMAND "
221 "NEXUIZ_PLAYERMODEL "
223 "PRYDON_CLIENTCURSOR "
224 "TENEBRAE_GFX_DLIGHTS "
227 //"EXT_CSQC " // not ready yet
234 This is the only valid way to move an object without using the physics of the world (setting velocity and waiting). Directly changing origin will not set internal links correctly, so clipping would be messed up. This should be called when an object is spawned, and then only if it is teleported.
236 setorigin (entity, origin)
239 static void VM_SV_setorigin(prvm_prog_t *prog)
244 VM_SAFEPARMCOUNT(2, VM_setorigin);
246 e = PRVM_G_EDICT(OFS_PARM0);
247 if (e == prog->edicts)
249 VM_Warning(prog, "setorigin: can not modify world entity\n");
252 if (e->priv.server->free)
254 VM_Warning(prog, "setorigin: can not modify free entity\n");
257 org = PRVM_G_VECTOR(OFS_PARM1);
258 VectorCopy (org, PRVM_serveredictvector(e, origin));
259 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
260 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
264 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
265 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qboolean rotate)
269 for (i=0 ; i<3 ; i++)
271 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
273 // set derived values
274 VectorCopy (min, PRVM_serveredictvector(e, mins));
275 VectorCopy (max, PRVM_serveredictvector(e, maxs));
276 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
285 the size box is rotated by the current angle
286 LordHavoc: no it isn't...
288 setsize (entity, minvector, maxvector)
291 static void VM_SV_setsize(prvm_prog_t *prog)
296 VM_SAFEPARMCOUNT(3, VM_setsize);
298 e = PRVM_G_EDICT(OFS_PARM0);
299 if (e == prog->edicts)
301 VM_Warning(prog, "setsize: can not modify world entity\n");
304 if (e->priv.server->free)
306 VM_Warning(prog, "setsize: can not modify free entity\n");
309 min = PRVM_G_VECTOR(OFS_PARM1);
310 max = PRVM_G_VECTOR(OFS_PARM2);
311 SetMinMaxSize(prog, e, min, max, false);
319 setmodel(entity, model)
322 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
323 static void VM_SV_setmodel(prvm_prog_t *prog)
329 VM_SAFEPARMCOUNT(2, VM_setmodel);
331 e = PRVM_G_EDICT(OFS_PARM0);
332 if (e == prog->edicts)
334 VM_Warning(prog, "setmodel: can not modify world entity\n");
337 if (e->priv.server->free)
339 VM_Warning(prog, "setmodel: can not modify free entity\n");
342 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
343 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
344 PRVM_serveredictfloat(e, modelindex) = i;
346 mod = SV_GetModelByIndex(i);
350 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
351 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
353 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
356 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
363 single print to a specific client
365 sprint(clientent, value)
368 static void VM_SV_sprint(prvm_prog_t *prog)
372 char string[VM_STRINGTEMP_LENGTH];
374 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
376 VM_VarString(prog, 1, string, sizeof(string));
378 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
379 // LordHavoc: div0 requested that sprintto world operate like print
386 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
388 VM_Warning(prog, "tried to centerprint to a non-client\n");
392 client = svs.clients + entnum-1;
393 if (!client->netconnection)
396 MSG_WriteChar(&client->netconnection->message,svc_print);
397 MSG_WriteString(&client->netconnection->message, string);
405 single print to a specific client
407 centerprint(clientent, value)
410 static void VM_SV_centerprint(prvm_prog_t *prog)
414 char string[VM_STRINGTEMP_LENGTH];
416 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
418 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
420 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
422 VM_Warning(prog, "tried to centerprint to a non-client\n");
426 client = svs.clients + entnum-1;
427 if (!client->netconnection)
430 VM_VarString(prog, 1, string, sizeof(string));
431 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
432 MSG_WriteString(&client->netconnection->message, string);
439 particle(origin, color, count)
442 static void VM_SV_particle(prvm_prog_t *prog)
448 VM_SAFEPARMCOUNT(4, VM_SV_particle);
450 org = PRVM_G_VECTOR(OFS_PARM0);
451 dir = PRVM_G_VECTOR(OFS_PARM1);
452 color = PRVM_G_FLOAT(OFS_PARM2);
453 count = PRVM_G_FLOAT(OFS_PARM3);
454 SV_StartParticle (org, dir, (int)color, (int)count);
464 static void VM_SV_ambientsound(prvm_prog_t *prog)
468 float vol, attenuation;
471 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
473 pos = PRVM_G_VECTOR (OFS_PARM0);
474 samp = PRVM_G_STRING(OFS_PARM1);
475 vol = PRVM_G_FLOAT(OFS_PARM2);
476 attenuation = PRVM_G_FLOAT(OFS_PARM3);
478 // check to see if samp was properly precached
479 soundnum = SV_SoundIndex(samp, 1);
487 // add an svc_spawnambient command to the level signon packet
490 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
492 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
494 MSG_WriteVector(&sv.signon, pos, sv.protocol);
496 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
497 MSG_WriteShort (&sv.signon, soundnum);
499 MSG_WriteByte (&sv.signon, soundnum);
501 MSG_WriteByte (&sv.signon, (int)(vol*255));
502 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
510 Each entity can have eight independant sound sources, like voice,
513 Channel 0 is an auto-allocate channel, the others override anything
514 already running on that entity/channel pair.
516 An attenuation of 0 will play full volume everywhere in the level.
517 Larger attenuations will drop off.
521 static void VM_SV_sound(prvm_prog_t *prog)
525 prvm_edict_t *entity;
531 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
533 entity = PRVM_G_EDICT(OFS_PARM0);
534 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
535 sample = PRVM_G_STRING(OFS_PARM2);
536 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
539 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
543 attenuation = PRVM_G_FLOAT(OFS_PARM4);
547 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
552 if(channel >= 8 && channel <= 15) // weird QW feature
554 flags |= CHANFLAG_RELIABLE;
559 flags = PRVM_G_FLOAT(OFS_PARM6);
561 if (volume < 0 || volume > 255)
563 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
567 if (attenuation < 0 || attenuation > 4)
569 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
573 channel = CHAN_USER2ENGINE(channel);
575 if (!IS_CHAN(channel))
577 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
581 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE, pitchchange);
588 Follows the same logic as VM_SV_sound, except instead of
589 an entity, an origin for the sound is provided, and channel
590 is omitted (since no entity is being tracked).
594 static void VM_SV_pointsound(prvm_prog_t *prog)
602 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
604 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
605 sample = PRVM_G_STRING(OFS_PARM1);
606 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
607 attenuation = PRVM_G_FLOAT(OFS_PARM3);
608 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
610 if (volume < 0 || volume > 255)
612 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
616 if (attenuation < 0 || attenuation > 4)
618 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
622 SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
629 Used for use tracing and shot targeting
630 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
631 if the tryents flag is set.
633 traceline (vector1, vector2, movetype, ignore)
636 static void VM_SV_traceline(prvm_prog_t *prog)
643 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
645 prog->xfunction->builtinsprofile += 30;
647 v1 = PRVM_G_VECTOR(OFS_PARM0);
648 v2 = PRVM_G_VECTOR(OFS_PARM1);
649 move = (int)PRVM_G_FLOAT(OFS_PARM2);
650 ent = PRVM_G_EDICT(OFS_PARM3);
652 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]))
653 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));
655 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
657 VM_SetTraceGlobals(prog, &trace);
665 Used for use tracing and shot targeting
666 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
667 if the tryents flag is set.
669 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
672 // LordHavoc: added this for my own use, VERY useful, similar to traceline
673 static void VM_SV_tracebox(prvm_prog_t *prog)
675 float *v1, *v2, *m1, *m2;
680 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
682 prog->xfunction->builtinsprofile += 30;
684 v1 = PRVM_G_VECTOR(OFS_PARM0);
685 m1 = PRVM_G_VECTOR(OFS_PARM1);
686 m2 = PRVM_G_VECTOR(OFS_PARM2);
687 v2 = PRVM_G_VECTOR(OFS_PARM3);
688 move = (int)PRVM_G_FLOAT(OFS_PARM4);
689 ent = PRVM_G_EDICT(OFS_PARM5);
691 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]))
692 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));
694 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
696 VM_SetTraceGlobals(prog, &trace);
699 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
704 vec3_t original_origin;
705 vec3_t original_velocity;
706 vec3_t original_angles;
707 vec3_t original_avelocity;
710 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
711 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
712 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
713 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
715 gravity = PRVM_serveredictfloat(tossent, gravity);
718 gravity *= sv_gravity.value * 0.025;
720 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
722 SV_CheckVelocity (tossent);
723 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
724 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
725 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
726 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
727 trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
728 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
729 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
731 if (trace.fraction < 1)
735 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
736 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
737 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
738 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
743 static void VM_SV_tracetoss(prvm_prog_t *prog)
747 prvm_edict_t *ignore;
749 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
751 prog->xfunction->builtinsprofile += 600;
753 ent = PRVM_G_EDICT(OFS_PARM0);
754 if (ent == prog->edicts)
756 VM_Warning(prog, "tracetoss: can not use world entity\n");
759 ignore = PRVM_G_EDICT(OFS_PARM1);
761 trace = SV_Trace_Toss(prog, ent, ignore);
763 VM_SetTraceGlobals(prog, &trace);
766 //============================================================================
768 static int checkpvsbytes;
769 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
771 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
777 // cycle to the next one
779 check = bound(1, check, svs.maxclients);
780 if (check == svs.maxclients)
788 prog->xfunction->builtinsprofile++;
790 if (i == svs.maxclients+1)
792 // look up the client's edict
793 ent = PRVM_EDICT_NUM(i);
794 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
795 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
797 // found a valid client (possibly the same one again)
801 // get the PVS for the entity
802 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
804 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
805 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
814 Returns a client (or object that has a client enemy) that would be a
817 If there is more than one valid option, they are cycled each frame
819 If (self.origin + self.viewofs) is not in the PVS of the current target,
820 it is not returned at all.
825 int c_invis, c_notvis;
826 static void VM_SV_checkclient(prvm_prog_t *prog)
828 prvm_edict_t *ent, *self;
831 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
833 // find a new check if on a new frame
834 if (sv.time - sv.lastchecktime >= 0.1)
836 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
837 sv.lastchecktime = sv.time;
840 // return check if it might be visible
841 ent = PRVM_EDICT_NUM(sv.lastcheck);
842 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
844 VM_RETURN_EDICT(prog->edicts);
848 // if current entity can't possibly see the check entity, return 0
849 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
850 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
851 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
854 VM_RETURN_EDICT(prog->edicts);
858 // might be able to see it
860 VM_RETURN_EDICT(ent);
863 //============================================================================
869 Checks if an entity is in a point's PVS.
870 Should be fast but can be inexact.
872 float checkpvs(vector viewpos, entity viewee) = #240;
875 static void VM_SV_checkpvs(prvm_prog_t *prog)
878 prvm_edict_t *viewee;
883 unsigned char fatpvs[MAX_MAP_LEAFS/8];
886 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
887 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
888 viewee = PRVM_G_EDICT(OFS_PARM1);
890 if(viewee->priv.server->free)
892 VM_Warning(prog, "checkpvs: can not check free entity\n");
893 PRVM_G_FLOAT(OFS_RETURN) = 4;
898 if(!sv.worldmodel || !sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
900 // no PVS support on this worldmodel... darn
901 PRVM_G_FLOAT(OFS_RETURN) = 3;
904 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
907 // viewpos isn't in any PVS... darn
908 PRVM_G_FLOAT(OFS_RETURN) = 2;
911 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
913 // using fat PVS like FTEQW does (slow)
914 if(!sv.worldmodel || !sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
916 // no PVS support on this worldmodel... darn
917 PRVM_G_FLOAT(OFS_RETURN) = 3;
920 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
923 // viewpos isn't in any PVS... darn
924 PRVM_G_FLOAT(OFS_RETURN) = 2;
927 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
936 Sends text over to the client's execution buffer
938 stuffcmd (clientent, value, ...)
941 static void VM_SV_stuffcmd(prvm_prog_t *prog)
945 char string[VM_STRINGTEMP_LENGTH];
947 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
949 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
950 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
952 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
956 VM_VarString(prog, 1, string, sizeof(string));
959 host_client = svs.clients + entnum-1;
960 Host_ClientCommands ("%s", string);
968 Returns a chain of entities that have origins within a spherical area
970 findradius (origin, radius)
973 static void VM_SV_findradius(prvm_prog_t *prog)
975 prvm_edict_t *ent, *chain;
976 vec_t radius, radius2;
977 vec3_t org, eorg, mins, maxs;
980 static prvm_edict_t *touchedicts[MAX_EDICTS];
983 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
986 chainfield = PRVM_G_INT(OFS_PARM2);
988 chainfield = prog->fieldoffsets.chain;
990 prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
992 chain = (prvm_edict_t *)prog->edicts;
994 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
995 radius = PRVM_G_FLOAT(OFS_PARM1);
996 radius2 = radius * radius;
998 mins[0] = org[0] - (radius + 1);
999 mins[1] = org[1] - (radius + 1);
1000 mins[2] = org[2] - (radius + 1);
1001 maxs[0] = org[0] + (radius + 1);
1002 maxs[1] = org[1] + (radius + 1);
1003 maxs[2] = org[2] + (radius + 1);
1004 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1005 if (numtouchedicts > MAX_EDICTS)
1007 // this never happens
1008 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1009 numtouchedicts = MAX_EDICTS;
1011 for (i = 0;i < numtouchedicts;i++)
1013 ent = touchedicts[i];
1014 prog->xfunction->builtinsprofile++;
1015 // Quake did not return non-solid entities but darkplaces does
1016 // (note: this is the reason you can't blow up fallen zombies)
1017 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1019 // LordHavoc: compare against bounding box rather than center so it
1020 // doesn't miss large objects, and use DotProduct instead of Length
1021 // for a major speedup
1022 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1023 if (sv_gameplayfix_findradiusdistancetobox.integer)
1025 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1026 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1027 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1030 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1031 if (DotProduct(eorg, eorg) < radius2)
1033 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1038 VM_RETURN_EDICT(chain);
1041 static void VM_SV_precache_sound(prvm_prog_t *prog)
1043 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1044 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1047 static void VM_SV_precache_model(prvm_prog_t *prog)
1049 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1050 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1051 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1058 float(float yaw, float dist[, settrace]) walkmove
1061 static void VM_SV_walkmove(prvm_prog_t *prog)
1070 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1072 // assume failure if it returns early
1073 PRVM_G_FLOAT(OFS_RETURN) = 0;
1075 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1076 if (ent == prog->edicts)
1078 VM_Warning(prog, "walkmove: can not modify world entity\n");
1081 if (ent->priv.server->free)
1083 VM_Warning(prog, "walkmove: can not modify free entity\n");
1086 yaw = PRVM_G_FLOAT(OFS_PARM0);
1087 dist = PRVM_G_FLOAT(OFS_PARM1);
1088 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1090 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1093 yaw = yaw*M_PI*2 / 360;
1095 move[0] = cos(yaw)*dist;
1096 move[1] = sin(yaw)*dist;
1099 // save program state, because SV_movestep may call other progs
1100 oldf = prog->xfunction;
1101 oldself = PRVM_serverglobaledict(self);
1103 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1106 // restore program state
1107 prog->xfunction = oldf;
1108 PRVM_serverglobaledict(self) = oldself;
1119 static void VM_SV_droptofloor(prvm_prog_t *prog)
1125 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1127 // assume failure if it returns early
1128 PRVM_G_FLOAT(OFS_RETURN) = 0;
1130 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1131 if (ent == prog->edicts)
1133 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1136 if (ent->priv.server->free)
1138 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1142 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1145 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1146 if (sv_gameplayfix_unstickentities.integer)
1147 SV_UnstickEntity(ent);
1149 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1150 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1153 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]);
1154 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1155 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1156 VectorSubtract(trace.endpos, offset, trace.endpos);
1157 if (trace.startsolid)
1159 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]);
1160 if (sv_gameplayfix_unstickentities.integer)
1161 SV_UnstickEntity(ent);
1163 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1164 PRVM_serveredictedict(ent, groundentity) = 0;
1165 PRVM_G_FLOAT(OFS_RETURN) = 1;
1167 else if (trace.fraction < 1)
1169 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]);
1170 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1171 if (sv_gameplayfix_unstickentities.integer)
1172 SV_UnstickEntity(ent);
1174 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1175 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1176 PRVM_G_FLOAT(OFS_RETURN) = 1;
1177 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1178 ent->priv.server->suspendedinairflag = true;
1183 if (trace.fraction != 1)
1185 if (trace.fraction < 1)
1186 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1188 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1189 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1190 PRVM_G_FLOAT(OFS_RETURN) = 1;
1191 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1192 ent->priv.server->suspendedinairflag = true;
1201 void(float style, string value) lightstyle
1204 static void VM_SV_lightstyle(prvm_prog_t *prog)
1211 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1213 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1214 val = PRVM_G_STRING(OFS_PARM1);
1216 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1217 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1220 // change the string in sv
1221 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1223 // send message to all clients on this server
1224 if (sv.state != ss_active)
1227 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1229 if (client->active && client->netconnection)
1231 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1232 MSG_WriteChar (&client->netconnection->message,style);
1233 MSG_WriteString (&client->netconnection->message, val);
1243 static void VM_SV_checkbottom(prvm_prog_t *prog)
1245 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1246 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1254 static void VM_SV_pointcontents(prvm_prog_t *prog)
1256 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1257 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1264 Pick a vector for the player to shoot along
1265 vector aim(entity, missilespeed)
1268 static void VM_SV_aim(prvm_prog_t *prog)
1270 prvm_edict_t *ent, *check, *bestent;
1271 vec3_t start, dir, end, bestdir;
1274 float dist, bestdist;
1277 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1279 // assume failure if it returns early
1280 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1281 // if sv_aim is so high it can't possibly accept anything, skip out early
1282 if (sv_aim.value >= 1)
1285 ent = PRVM_G_EDICT(OFS_PARM0);
1286 if (ent == prog->edicts)
1288 VM_Warning(prog, "aim: can not use world entity\n");
1291 if (ent->priv.server->free)
1293 VM_Warning(prog, "aim: can not use free entity\n");
1296 //speed = PRVM_G_FLOAT(OFS_PARM1);
1298 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1301 // try sending a trace straight
1302 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1303 VectorMA (start, 2048, dir, end);
1304 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1305 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1306 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1308 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1313 // try all possible entities
1314 VectorCopy (dir, bestdir);
1315 bestdist = sv_aim.value;
1318 check = PRVM_NEXT_EDICT(prog->edicts);
1319 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1321 prog->xfunction->builtinsprofile++;
1322 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1326 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1327 continue; // don't aim at teammate
1328 for (j=0 ; j<3 ; j++)
1329 end[j] = PRVM_serveredictvector(check, origin)[j]
1330 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1331 VectorSubtract (end, start, dir);
1332 VectorNormalize (dir);
1333 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1334 if (dist < bestdist)
1335 continue; // to far to turn
1336 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1337 if (tr.ent == check)
1338 { // can shoot at this one
1346 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1347 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1348 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1350 VectorNormalize (end);
1351 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1355 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1360 ===============================================================================
1364 ===============================================================================
1367 #define MSG_BROADCAST 0 // unreliable to all
1368 #define MSG_ONE 1 // reliable to one (msg_entity)
1369 #define MSG_ALL 2 // reliable to all
1370 #define MSG_INIT 3 // write to the init string
1371 #define MSG_ENTITY 5
1373 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1379 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1383 return &sv.datagram;
1386 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1387 entnum = PRVM_NUM_FOR_EDICT(ent);
1388 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1390 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1391 return &sv.reliable_datagram;
1394 return &svs.clients[entnum-1].netconnection->message;
1397 VM_Warning(prog, "WriteDest: bad destination\n");
1399 return &sv.reliable_datagram;
1405 return sv.writeentitiestoclient_msg;
1411 static void VM_SV_WriteByte(prvm_prog_t *prog)
1413 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1414 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1417 static void VM_SV_WriteChar(prvm_prog_t *prog)
1419 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1420 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1423 static void VM_SV_WriteShort(prvm_prog_t *prog)
1425 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1426 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1429 static void VM_SV_WriteLong(prvm_prog_t *prog)
1431 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1432 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1435 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1437 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1438 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1441 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1443 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1444 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1447 static void VM_SV_WriteString(prvm_prog_t *prog)
1449 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1450 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1453 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1455 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1456 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1460 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1462 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1463 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1466 // writes a picture as at most size bytes of data
1468 // IMGNAME \0 SIZE(short) IMGDATA
1469 // if failed to read/compress:
1471 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1472 static void VM_SV_WritePicture(prvm_prog_t *prog)
1474 const char *imgname;
1478 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1480 imgname = PRVM_G_STRING(OFS_PARM1);
1481 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1485 MSG_WriteString(WriteDest(prog), imgname);
1486 if(Image_Compress(imgname, size, &buf, &size))
1489 MSG_WriteShort(WriteDest(prog), size);
1490 SZ_Write(WriteDest(prog), (unsigned char *) buf, size);
1495 MSG_WriteShort(WriteDest(prog), 0);
1499 //////////////////////////////////////////////////////////
1501 static void VM_SV_makestatic(prvm_prog_t *prog)
1506 // allow 0 parameters due to an id1 qc bug in which this function is used
1507 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1508 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1510 if (prog->argc >= 1)
1511 ent = PRVM_G_EDICT(OFS_PARM0);
1513 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1514 if (ent == prog->edicts)
1516 VM_Warning(prog, "makestatic: can not modify world entity\n");
1519 if (ent->priv.server->free)
1521 VM_Warning(prog, "makestatic: can not modify free entity\n");
1526 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1531 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1532 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1533 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1535 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1537 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1538 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1539 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1543 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1544 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1545 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1548 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1549 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1550 for (i=0 ; i<3 ; i++)
1552 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1553 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1556 // throw the entity away now
1557 PRVM_ED_Free(prog, ent);
1560 //=============================================================================
1567 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1573 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1575 ent = PRVM_G_EDICT(OFS_PARM0);
1576 i = PRVM_NUM_FOR_EDICT(ent);
1577 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1579 Con_Print("tried to setspawnparms on a non-client\n");
1583 // copy spawn parms out of the client_t
1584 client = svs.clients + i-1;
1585 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1586 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1593 Returns a color vector indicating the lighting at the requested point.
1595 (Internal Operation note: actually measures the light beneath the point, just like
1596 the model lighting on the client)
1601 static void VM_SV_getlight(prvm_prog_t *prog)
1603 vec3_t ambientcolor, diffusecolor, diffusenormal;
1605 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1606 p = PRVM_G_VECTOR(OFS_PARM0);
1607 VectorClear(ambientcolor);
1608 VectorClear(diffusecolor);
1609 VectorClear(diffusenormal);
1610 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1611 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1612 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1617 unsigned char type; // 1/2/8 or other value if isn't used
1621 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1622 static int vm_customstats_last;
1624 void VM_CustomStats_Clear (void)
1628 Z_Free(vm_customstats);
1629 vm_customstats = NULL;
1630 vm_customstats_last = -1;
1634 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1636 prvm_prog_t *prog = SVVM_prog;
1643 for(i=0; i<vm_customstats_last+1 ;i++)
1645 if(!vm_customstats[i].type)
1647 switch(vm_customstats[i].type)
1649 //string as 16 bytes
1652 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1653 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1654 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1655 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1656 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1658 //float field sent as-is
1660 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1662 //integer value of float field
1664 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1672 // void(float index, float type, .void field) SV_AddStat = #232;
1673 // Set up an auto-sent player stat.
1674 // Client's get thier own fields sent to them. Index may not be less than 32.
1675 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1676 // 1: string (4 stats carrying a total of 16 charactures)
1677 // 2: float (one stat, float converted to an integer for transportation)
1678 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1679 static void VM_SV_AddStat(prvm_prog_t *prog)
1684 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1688 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1691 VM_Warning(prog, "PF_SV_AddStat: not enough memory\n");
1695 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1696 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1697 off = PRVM_G_INT (OFS_PARM2);
1702 VM_Warning(prog, "PF_SV_AddStat: index may not be less than 32\n");
1705 if(i >= (MAX_CL_STATS-32))
1707 VM_Warning(prog, "PF_SV_AddStat: index >= MAX_CL_STATS\n");
1710 if(i > (MAX_CL_STATS-32-4) && type == 1)
1712 VM_Warning(prog, "PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1715 vm_customstats[i].type = type;
1716 vm_customstats[i].fieldoffset = off;
1717 if(vm_customstats_last < i)
1718 vm_customstats_last = i;
1725 copies data from one entity to another
1727 copyentity(src, dst)
1730 static void VM_SV_copyentity(prvm_prog_t *prog)
1732 prvm_edict_t *in, *out;
1733 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1734 in = PRVM_G_EDICT(OFS_PARM0);
1735 if (in == prog->edicts)
1737 VM_Warning(prog, "copyentity: can not read world entity\n");
1740 if (in->priv.server->free)
1742 VM_Warning(prog, "copyentity: can not read free entity\n");
1745 out = PRVM_G_EDICT(OFS_PARM1);
1746 if (out == prog->edicts)
1748 VM_Warning(prog, "copyentity: can not modify world entity\n");
1751 if (out->priv.server->free)
1753 VM_Warning(prog, "copyentity: can not modify free entity\n");
1756 memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
1765 sets the color of a client and broadcasts the update to all connected clients
1767 setcolor(clientent, value)
1770 static void VM_SV_setcolor(prvm_prog_t *prog)
1775 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1776 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1777 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1779 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1781 Con_Print("tried to setcolor a non-client\n");
1785 client = svs.clients + entnum-1;
1788 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1789 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1792 if (client->old_colors != client->colors)
1794 client->old_colors = client->colors;
1795 // send notification to all clients
1796 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1797 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1798 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1806 effect(origin, modelname, startframe, framecount, framerate)
1809 static void VM_SV_effect(prvm_prog_t *prog)
1813 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1814 s = PRVM_G_STRING(OFS_PARM1);
1817 VM_Warning(prog, "effect: no model specified\n");
1821 i = SV_ModelIndex(s, 1);
1824 VM_Warning(prog, "effect: model not precached\n");
1828 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1830 VM_Warning(prog, "effect: framecount < 1\n");
1834 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1836 VM_Warning(prog, "effect: framerate < 1\n");
1840 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));
1843 static void VM_SV_te_blood(prvm_prog_t *prog)
1845 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1846 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1848 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1849 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1851 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1852 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1853 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1855 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1856 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1857 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1859 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1860 SV_FlushBroadcastMessages();
1863 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1865 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1866 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1868 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1869 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1873 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1875 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1876 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1877 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1879 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1881 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1882 SV_FlushBroadcastMessages();
1885 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1887 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1888 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1889 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1891 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1892 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1893 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1895 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1896 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1897 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1898 SV_FlushBroadcastMessages();
1901 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1903 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1904 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1906 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1907 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1911 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1913 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1914 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1915 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1917 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1918 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1919 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1921 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1923 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1924 // gravity true/false
1925 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1928 SV_FlushBroadcastMessages();
1931 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1933 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1934 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1936 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1937 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1941 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1943 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1944 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1945 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1948 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1949 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1951 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1953 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1954 SV_FlushBroadcastMessages();
1957 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1959 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1960 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1962 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1963 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1965 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1970 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1973 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1974 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1975 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1977 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1979 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1980 SV_FlushBroadcastMessages();
1983 static void VM_SV_te_spark(prvm_prog_t *prog)
1985 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1986 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1988 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1989 MSG_WriteByte(&sv.datagram, TE_SPARK);
1991 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1992 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1993 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1995 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1996 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1997 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1999 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2000 SV_FlushBroadcastMessages();
2003 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2005 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2006 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2007 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2009 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2010 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2011 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2012 SV_FlushBroadcastMessages();
2015 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2017 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2018 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2019 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2021 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2022 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2023 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2024 SV_FlushBroadcastMessages();
2027 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2029 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2030 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2031 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2033 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2034 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2035 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2036 SV_FlushBroadcastMessages();
2039 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2041 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2042 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2043 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2045 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2046 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2047 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2048 SV_FlushBroadcastMessages();
2051 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2053 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2054 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2055 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2058 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2059 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2060 SV_FlushBroadcastMessages();
2063 static void VM_SV_te_customflash(prvm_prog_t *prog)
2065 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2066 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2068 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2069 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2071 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2072 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2075 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2077 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2079 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2080 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2081 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2082 SV_FlushBroadcastMessages();
2085 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2087 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2088 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2089 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2091 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2092 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2093 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2094 SV_FlushBroadcastMessages();
2097 static void VM_SV_te_spike(prvm_prog_t *prog)
2099 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2100 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2101 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2103 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2104 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2105 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2106 SV_FlushBroadcastMessages();
2109 static void VM_SV_te_superspike(prvm_prog_t *prog)
2111 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2112 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2113 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2115 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2116 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2117 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2118 SV_FlushBroadcastMessages();
2121 static void VM_SV_te_explosion(prvm_prog_t *prog)
2123 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2124 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2125 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2127 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2128 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2129 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2130 SV_FlushBroadcastMessages();
2133 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2135 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2136 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2137 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2139 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2140 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2141 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2142 SV_FlushBroadcastMessages();
2145 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2147 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2148 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2149 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2151 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2152 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2153 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2154 SV_FlushBroadcastMessages();
2157 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2159 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2160 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2161 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2163 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2164 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2165 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2166 SV_FlushBroadcastMessages();
2169 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2171 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2172 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2173 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2175 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2176 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2177 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2178 SV_FlushBroadcastMessages();
2181 static void VM_SV_te_teleport(prvm_prog_t *prog)
2183 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2184 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2185 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2187 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2188 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2189 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2190 SV_FlushBroadcastMessages();
2193 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2195 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2196 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2197 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2199 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2200 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2201 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2203 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2204 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2205 SV_FlushBroadcastMessages();
2208 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2210 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2211 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2212 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2214 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2216 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2217 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2218 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2220 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2221 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2222 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2223 SV_FlushBroadcastMessages();
2226 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2228 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2229 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2230 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2232 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2234 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2235 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2236 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2238 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2239 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2240 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2241 SV_FlushBroadcastMessages();
2244 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2246 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2247 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2248 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2250 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2252 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2253 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2254 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2256 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2257 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2258 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2259 SV_FlushBroadcastMessages();
2262 static void VM_SV_te_beam(prvm_prog_t *prog)
2264 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2265 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2266 MSG_WriteByte(&sv.datagram, TE_BEAM);
2268 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2270 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2271 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2272 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2274 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2275 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2276 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2277 SV_FlushBroadcastMessages();
2280 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2282 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2283 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2284 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2285 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2286 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2287 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2288 SV_FlushBroadcastMessages();
2291 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2293 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2294 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2295 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2297 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2298 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2299 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2301 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2302 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2303 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2305 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2306 SV_FlushBroadcastMessages();
2309 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2310 //this function originally written by KrimZon, made shorter by LordHavoc
2311 static void VM_SV_clientcommand(prvm_prog_t *prog)
2313 client_t *temp_client;
2315 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2317 //find client for this entity
2318 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2319 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2321 Con_Print("PF_clientcommand: entity is not a client\n");
2325 temp_client = host_client;
2326 host_client = svs.clients + i;
2327 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
2328 host_client = temp_client;
2331 //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)
2332 static void VM_SV_setattachment(prvm_prog_t *prog)
2334 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2335 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2336 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2339 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2341 if (e == prog->edicts)
2343 VM_Warning(prog, "setattachment: can not modify world entity\n");
2346 if (e->priv.server->free)
2348 VM_Warning(prog, "setattachment: can not modify free entity\n");
2352 if (tagentity == NULL)
2353 tagentity = prog->edicts;
2357 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2359 model = SV_GetModelFromEdict(tagentity);
2362 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2364 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);
2367 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));
2370 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2371 PRVM_serveredictfloat(e, tag_index) = tagindex;
2374 /////////////////////////////////////////
2375 // DP_MD3_TAGINFO extension coded by VorteX
2377 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2381 i = (int)PRVM_serveredictfloat(e, modelindex);
2382 if (i < 1 || i >= MAX_MODELS)
2385 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2388 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2395 Matrix4x4_CreateIdentity(tag_localmatrix);
2397 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2399 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2410 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2413 float pitchsign = 1;
2415 scale = PRVM_serveredictfloat(ent, scale);
2420 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);
2423 pitchsign = SV_GetPitchSign(prog, ent);
2424 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);
2428 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2431 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2433 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2434 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2435 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2436 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2438 *out = identitymatrix;
2442 // Warnings/errors code:
2443 // 0 - normal (everything all-right)
2446 // 3 - null or non-precached model
2447 // 4 - no tags with requested index
2448 // 5 - runaway loop at attachment chain
2449 extern cvar_t cl_bob;
2450 extern cvar_t cl_bobcycle;
2451 extern cvar_t cl_bobup;
2452 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2455 int modelindex, attachloop;
2456 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2459 *out = identitymatrix; // warnings and errors return identical matrix
2461 if (ent == prog->edicts)
2463 if (ent->priv.server->free)
2466 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2467 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2470 model = SV_GetModelByIndex(modelindex);
2472 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2473 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2474 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2476 tagmatrix = identitymatrix;
2477 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2481 if (attachloop >= 256) // prevent runaway looping
2483 // apply transformation by child's tagindex on parent entity and then
2484 // by parent entity itself
2485 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2486 if (ret && attachloop == 0)
2488 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2489 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2490 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2491 // next iteration we process the parent entity
2492 if (PRVM_serveredictedict(ent, tag_entity))
2494 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2495 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2502 // RENDER_VIEWMODEL magic
2503 if (PRVM_serveredictedict(ent, viewmodelforclient))
2505 Matrix4x4_Copy(&tagmatrix, out);
2506 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2508 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2509 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2512 // Cl_bob, ported from rendering code
2513 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2516 // LordHavoc: this code is *weird*, but not replacable (I think it
2517 // should be done in QC on the server, but oh well, quake is quake)
2518 // LordHavoc: figured out bobup: the time at which the sin is at 180
2519 // degrees (which allows lengthening or squishing the peak or valley)
2520 cycle = sv.time/cl_bobcycle.value;
2521 cycle -= (int)cycle;
2522 if (cycle < cl_bobup.value)
2523 cycle = sin(M_PI * cycle / cl_bobup.value);
2525 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2526 // bob is proportional to velocity in the xy plane
2527 // (don't count Z, or jumping messes it up)
2528 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;
2529 bob = bob*0.3 + bob*0.7*cycle;
2530 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2537 //float(entity ent, string tagname) gettagindex;
2539 static void VM_SV_gettagindex(prvm_prog_t *prog)
2542 const char *tag_name;
2545 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2547 ent = PRVM_G_EDICT(OFS_PARM0);
2548 tag_name = PRVM_G_STRING(OFS_PARM1);
2550 if (ent == prog->edicts)
2552 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2555 if (ent->priv.server->free)
2557 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2562 if (!SV_GetModelFromEdict(ent))
2563 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2566 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2568 if(developer_extra.integer)
2569 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2571 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2574 //vector(entity ent, float tagindex) gettaginfo;
2575 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2579 matrix4x4_t tag_matrix;
2580 matrix4x4_t tag_localmatrix;
2582 const char *tagname;
2584 vec3_t fo, le, up, trans;
2585 const dp_model_t *model;
2587 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2589 e = PRVM_G_EDICT(OFS_PARM0);
2590 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2592 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2593 Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
2594 VectorScale(le, -1, PRVM_serverglobalvector(v_right));
2595 model = SV_GetModelFromEdict(e);
2596 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2597 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2598 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2599 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2600 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2602 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2603 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2604 VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
2605 VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
2606 VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
2607 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2612 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2615 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2618 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2621 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2624 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2629 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2630 static void VM_SV_dropclient(prvm_prog_t *prog)
2633 client_t *oldhostclient;
2634 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2635 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2636 if (clientnum < 0 || clientnum >= svs.maxclients)
2638 VM_Warning(prog, "dropclient: not a client\n");
2641 if (!svs.clients[clientnum].active)
2643 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2646 oldhostclient = host_client;
2647 host_client = svs.clients + clientnum;
2648 SV_DropClient(false);
2649 host_client = oldhostclient;
2652 //entity() spawnclient (DP_SV_BOTCLIENT)
2653 static void VM_SV_spawnclient(prvm_prog_t *prog)
2657 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2658 prog->xfunction->builtinsprofile += 2;
2660 for (i = 0;i < svs.maxclients;i++)
2662 if (!svs.clients[i].active)
2664 prog->xfunction->builtinsprofile += 100;
2665 SV_ConnectClient (i, NULL);
2666 // this has to be set or else ClientDisconnect won't be called
2667 // we assume the qc will call ClientConnect...
2668 svs.clients[i].clientconnectcalled = true;
2669 ed = PRVM_EDICT_NUM(i + 1);
2673 VM_RETURN_EDICT(ed);
2676 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2677 static void VM_SV_clienttype(prvm_prog_t *prog)
2680 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2681 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2682 if (clientnum < 0 || clientnum >= svs.maxclients)
2683 PRVM_G_FLOAT(OFS_RETURN) = 3;
2684 else if (!svs.clients[clientnum].active)
2685 PRVM_G_FLOAT(OFS_RETURN) = 0;
2686 else if (svs.clients[clientnum].netconnection)
2687 PRVM_G_FLOAT(OFS_RETURN) = 1;
2689 PRVM_G_FLOAT(OFS_RETURN) = 2;
2696 string(string key) serverkey
2699 static void VM_SV_serverkey(prvm_prog_t *prog)
2701 char string[VM_STRINGTEMP_LENGTH];
2702 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2703 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2704 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2707 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2708 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2713 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2715 e = PRVM_G_EDICT(OFS_PARM0);
2716 if (e == prog->edicts)
2718 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2721 if (e->priv.server->free)
2723 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2726 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2727 if (i <= 0 || i >= MAX_MODELS)
2729 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2732 if (!sv.model_precache[i][0])
2734 VM_Warning(prog, "setmodelindex: model not precached\n");
2738 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2739 PRVM_serveredictfloat(e, modelindex) = i;
2741 mod = SV_GetModelByIndex(i);
2745 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2746 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2748 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2751 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2754 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2755 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2758 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2760 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2762 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2763 if (i <= 0 || i >= MAX_MODELS)
2765 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2768 if (!sv.model_precache[i][0])
2770 VM_Warning(prog, "modelnameforindex: model not precached\n");
2774 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2777 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2778 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2781 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2782 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2785 PRVM_G_FLOAT(OFS_RETURN) = i;
2788 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2789 static void VM_SV_trailparticles(prvm_prog_t *prog)
2791 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2793 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2796 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2797 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2798 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2799 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2800 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2801 SV_FlushBroadcastMessages();
2804 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2805 static void VM_SV_pointparticles(prvm_prog_t *prog)
2807 int effectnum, count;
2809 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2811 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2814 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2815 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2816 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2817 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2818 if (count == 1 && !VectorLength2(vel))
2821 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2822 MSG_WriteShort(&sv.datagram, effectnum);
2823 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2827 // 1+2+12+12+2=29 bytes
2828 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2829 MSG_WriteShort(&sv.datagram, effectnum);
2830 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2831 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2832 MSG_WriteShort(&sv.datagram, count);
2835 SV_FlushBroadcastMessages();
2838 //PF_setpause, // void(float pause) setpause = #531;
2839 static void VM_SV_setpause(prvm_prog_t *prog) {
2841 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2842 if (pauseValue != 0) { //pause the game
2844 sv.pausedstart = realtime;
2845 } else { //disable pause, in case it was enabled
2846 if (sv.paused != 0) {
2851 // send notification to all clients
2852 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2853 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2856 // #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.
2857 static void VM_SV_skel_create(prvm_prog_t *prog)
2859 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2860 dp_model_t *model = SV_GetModelByIndex(modelindex);
2861 skeleton_t *skeleton;
2863 PRVM_G_FLOAT(OFS_RETURN) = 0;
2864 if (!model || !model->num_bones)
2866 for (i = 0;i < MAX_EDICTS;i++)
2867 if (!prog->skeletons[i])
2869 if (i == MAX_EDICTS)
2871 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(prog->progs_mempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2872 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2873 skeleton->model = model;
2874 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2875 // initialize to identity matrices
2876 for (i = 0;i < skeleton->model->num_bones;i++)
2877 skeleton->relativetransforms[i] = identitymatrix;
2880 // #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
2881 static void VM_SV_skel_build(prvm_prog_t *prog)
2883 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2884 skeleton_t *skeleton;
2885 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2886 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2887 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2888 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2889 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2890 dp_model_t *model = SV_GetModelByIndex(modelindex);
2895 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2896 frameblend_t frameblend[MAX_FRAMEBLENDS];
2897 matrix4x4_t blendedmatrix;
2899 PRVM_G_FLOAT(OFS_RETURN) = 0;
2900 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2902 firstbone = max(0, firstbone);
2903 lastbone = min(lastbone, model->num_bones - 1);
2904 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2905 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2906 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time);
2907 blendfrac = 1.0f - retainfrac;
2908 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2909 frameblend[numblends].lerp *= blendfrac;
2910 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2912 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2913 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2914 for (blendindex = 0;blendindex < numblends;blendindex++)
2916 Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2917 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2919 skeleton->relativetransforms[bonenum] = blendedmatrix;
2921 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2924 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2925 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
2927 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2928 skeleton_t *skeleton;
2929 PRVM_G_FLOAT(OFS_RETURN) = 0;
2930 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2932 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2935 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2936 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
2938 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2939 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2940 skeleton_t *skeleton;
2941 PRVM_G_INT(OFS_RETURN) = 0;
2942 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2944 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2946 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
2949 // #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)
2950 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
2952 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2953 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2954 skeleton_t *skeleton;
2955 PRVM_G_FLOAT(OFS_RETURN) = 0;
2956 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2958 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2960 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2963 // #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
2964 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
2966 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2967 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2968 skeleton_t *skeleton;
2969 PRVM_G_FLOAT(OFS_RETURN) = 0;
2970 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2972 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2975 // #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)
2976 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
2978 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2979 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2980 skeleton_t *skeleton;
2982 vec3_t forward, left, up, origin;
2983 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2984 VectorClear(PRVM_clientglobalvector(v_forward));
2985 VectorClear(PRVM_clientglobalvector(v_right));
2986 VectorClear(PRVM_clientglobalvector(v_up));
2987 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2989 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2991 matrix = skeleton->relativetransforms[bonenum];
2992 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2993 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2994 VectorNegate(left, PRVM_clientglobalvector(v_right));
2995 VectorCopy(up, PRVM_clientglobalvector(v_up));
2996 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2999 // #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)
3000 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
3002 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3003 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3004 skeleton_t *skeleton;
3007 vec3_t forward, left, up, origin;
3008 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3009 VectorClear(PRVM_clientglobalvector(v_forward));
3010 VectorClear(PRVM_clientglobalvector(v_right));
3011 VectorClear(PRVM_clientglobalvector(v_up));
3012 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3014 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3016 matrix = skeleton->relativetransforms[bonenum];
3017 // convert to absolute
3018 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3021 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3023 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3024 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3025 VectorNegate(left, PRVM_clientglobalvector(v_right));
3026 VectorCopy(up, PRVM_clientglobalvector(v_up));
3027 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3030 // #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)
3031 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3033 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3034 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3035 vec3_t forward, left, up, origin;
3036 skeleton_t *skeleton;
3038 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3040 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3042 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3043 VectorNegate(PRVM_clientglobalvector(v_right), left);
3044 VectorCopy(PRVM_clientglobalvector(v_up), up);
3045 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3046 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3047 skeleton->relativetransforms[bonenum] = matrix;
3050 // #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)
3051 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3053 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3054 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3055 vec3_t forward, left, up, origin;
3056 skeleton_t *skeleton;
3059 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3061 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3063 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3064 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3065 VectorNegate(PRVM_clientglobalvector(v_right), left);
3066 VectorCopy(PRVM_clientglobalvector(v_up), up);
3067 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3068 temp = skeleton->relativetransforms[bonenum];
3069 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3072 // #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)
3073 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3075 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3076 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3077 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3079 vec3_t forward, left, up, origin;
3080 skeleton_t *skeleton;
3083 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3085 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3086 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3087 VectorNegate(PRVM_clientglobalvector(v_right), left);
3088 VectorCopy(PRVM_clientglobalvector(v_up), up);
3089 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3090 firstbone = max(0, firstbone);
3091 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3092 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3094 temp = skeleton->relativetransforms[bonenum];
3095 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3099 // #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
3100 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3102 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3103 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3104 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3105 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3107 skeleton_t *skeletondst;
3108 skeleton_t *skeletonsrc;
3109 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3111 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3113 firstbone = max(0, firstbone);
3114 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3115 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3116 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3117 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3120 // #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)
3121 static void VM_SV_skel_delete(prvm_prog_t *prog)
3123 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3124 skeleton_t *skeleton;
3125 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3128 prog->skeletons[skeletonindex] = NULL;
3131 // #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
3132 static void VM_SV_frameforname(prvm_prog_t *prog)
3134 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3135 dp_model_t *model = SV_GetModelByIndex(modelindex);
3136 const char *name = PRVM_G_STRING(OFS_PARM1);
3138 PRVM_G_FLOAT(OFS_RETURN) = -1;
3139 if (!model || !model->animscenes)
3141 for (i = 0;i < model->numframes;i++)
3143 if (!strcasecmp(model->animscenes[i].name, name))
3145 PRVM_G_FLOAT(OFS_RETURN) = i;
3151 // #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.
3152 static void VM_SV_frameduration(prvm_prog_t *prog)
3154 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3155 dp_model_t *model = SV_GetModelByIndex(modelindex);
3156 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3157 PRVM_G_FLOAT(OFS_RETURN) = 0;
3158 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3160 if (model->animscenes[framenum].framerate)
3161 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3165 prvm_builtin_t vm_sv_builtins[] = {
3166 NULL, // #0 NULL function (not callable) (QUAKE)
3167 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3168 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3169 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3170 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3171 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3172 VM_break, // #6 void() break (QUAKE)
3173 VM_random, // #7 float() random (QUAKE)
3174 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3175 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3176 VM_error, // #10 void(string e) error (QUAKE)
3177 VM_objerror, // #11 void(string e) objerror (QUAKE)
3178 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3179 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3180 VM_spawn, // #14 entity() spawn (QUAKE)
3181 VM_remove, // #15 void(entity e) remove (QUAKE)
3182 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3183 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3184 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3185 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3186 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3187 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3188 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3189 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3190 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3191 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3192 VM_ftos, // #26 string(float f) ftos (QUAKE)
3193 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3194 VM_coredump, // #28 void() coredump (QUAKE)
3195 VM_traceon, // #29 void() traceon (QUAKE)
3196 VM_traceoff, // #30 void() traceoff (QUAKE)
3197 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3198 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3199 NULL, // #33 (QUAKE)
3200 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3201 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3202 VM_rint, // #36 float(float v) rint (QUAKE)
3203 VM_floor, // #37 float(float v) floor (QUAKE)
3204 VM_ceil, // #38 float(float v) ceil (QUAKE)
3205 NULL, // #39 (QUAKE)
3206 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3207 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3208 NULL, // #42 (QUAKE)
3209 VM_fabs, // #43 float(float f) fabs (QUAKE)
3210 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3211 VM_cvar, // #45 float(string s) cvar (QUAKE)
3212 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3213 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3214 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3215 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3216 NULL, // #50 (QUAKE)
3217 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3218 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3219 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3220 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3221 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3222 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3223 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3224 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3225 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3226 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3227 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3228 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3229 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3230 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3231 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3232 NULL, // #66 (QUAKE)
3233 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3234 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3235 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3236 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3237 NULL, // #71 (QUAKE)
3238 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3239 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3240 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3241 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3242 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3243 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3244 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3245 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3246 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3247 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3248 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3249 NULL, // #83 (QUAKE)
3250 NULL, // #84 (QUAKE)
3251 NULL, // #85 (QUAKE)
3252 NULL, // #86 (QUAKE)
3253 NULL, // #87 (QUAKE)
3254 NULL, // #88 (QUAKE)
3255 NULL, // #89 (QUAKE)
3256 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3257 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3258 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3259 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3260 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3261 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3262 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3263 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3264 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3265 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3266 // FrikaC and Telejano range #100-#199
3277 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3278 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3279 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3280 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3281 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3282 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3283 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3284 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3285 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3286 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3367 // FTEQW range #200-#299
3386 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3389 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3390 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3391 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3392 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3393 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3394 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3395 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3396 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3397 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3398 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3400 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3408 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3431 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.
3432 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
3433 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3434 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3435 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)
3436 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
3437 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)
3438 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)
3439 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)
3440 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)
3441 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)
3442 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
3443 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)
3444 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
3445 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.
3468 // CSQC range #300-#399
3469 NULL, // #300 void() clearscene (EXT_CSQC)
3470 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3471 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3472 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3473 NULL, // #304 void() renderscene (EXT_CSQC)
3474 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3475 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3476 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3477 NULL, // #308 void() R_EndPolygon
3479 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3480 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3484 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3485 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3486 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3487 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3488 NULL, // #319 void(string name) freepic (EXT_CSQC)
3489 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3490 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3491 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3492 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3493 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3494 NULL, // #325 void(void) drawresetcliparea
3499 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3500 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3501 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3502 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3503 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3504 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3505 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3506 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3507 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3508 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3509 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3510 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3511 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3512 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3513 NULL, // #344 vector() getmousepos (EXT_CSQC)
3514 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3515 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3516 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3517 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3518 NULL, // #349 float() isdemo (EXT_CSQC)
3519 VM_isserver, // #350 float() isserver (EXT_CSQC)
3520 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3521 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3522 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3523 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3529 NULL, // #360 float() readbyte (EXT_CSQC)
3530 NULL, // #361 float() readchar (EXT_CSQC)
3531 NULL, // #362 float() readshort (EXT_CSQC)
3532 NULL, // #363 float() readlong (EXT_CSQC)
3533 NULL, // #364 float() readcoord (EXT_CSQC)
3534 NULL, // #365 float() readangle (EXT_CSQC)
3535 NULL, // #366 string() readstring (EXT_CSQC)
3536 NULL, // #367 float() readfloat (EXT_CSQC)
3569 // LordHavoc's range #400-#499
3570 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3571 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3572 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3573 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3574 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3575 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3576 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3577 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3578 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)
3579 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3580 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3581 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3582 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3583 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3584 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3585 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3586 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3587 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3588 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3589 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3590 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3591 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3592 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3593 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3594 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3595 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3596 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3597 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3598 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3599 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3600 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3601 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3602 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3603 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3604 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3605 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3606 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3607 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3608 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3609 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3610 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3611 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3612 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3613 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3614 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3615 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3616 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3617 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3618 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3619 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3620 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3621 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3622 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3623 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3624 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3625 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3626 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3627 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3629 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3630 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3631 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3632 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3633 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3634 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3635 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3636 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3637 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3638 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3639 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3641 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3642 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3643 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3644 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3645 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3646 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3647 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3648 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3649 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3650 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3651 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3652 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3653 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3654 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3655 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3656 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3664 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3665 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3666 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3667 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3668 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3669 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3670 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3671 VM_SV_WritePicture, // #501
3673 VM_whichpack, // #503 string(string) whichpack = #503;
3680 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3681 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3682 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3683 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)
3684 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3685 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3686 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3687 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3688 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3689 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3699 VM_loadfromdata, // #529
3700 VM_loadfromfile, // #530
3701 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3703 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3704 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3705 VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP)
3706 VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP)
3707 VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP)
3708 VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP)
3710 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3711 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3712 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3775 VM_callfunction, // #605
3776 VM_writetofile, // #606
3777 VM_isfunction, // #607
3783 VM_parseentitydata, // #613
3794 VM_SV_getextresponse, // #624 string getextresponse(void)
3797 VM_sprintf, // #627 string sprintf(string format, ...)
3798 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3799 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3809 VM_digest_hex, // #639
3813 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3815 void SVVM_init_cmd(prvm_prog_t *prog)
3820 void SVVM_reset_cmd(prvm_prog_t *prog)
3822 World_End(&sv.world);
3823 if(PRVM_serverfunction(SV_Shutdown))
3825 func_t s = PRVM_serverfunction(SV_Shutdown);
3826 PRVM_serverglobalfloat(time) = sv.time;
3827 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3828 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");