6 //============================================================================
11 const char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
24 "DP_CSQC_ENTITYWORLDOBJECT "
25 "DP_CSQC_ENTITYMODELLIGHT "
26 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
27 "DP_CSQC_MULTIFRAME_INTERPOLATION "
28 "DP_CSQC_BOXPARTICLES "
29 "DP_CSQC_SPAWNPARTICLE "
30 "DP_CSQC_QUERYRENDERENTITY "
31 "DP_CSQC_ROTATEMOVES "
44 "DP_EF_RESTARTANIM_BIT "
49 "DP_ENT_CUSTOMCOLORMAP "
50 "DP_ENT_EXTERIORMODELTOCLIENT "
53 "DP_ENT_LOWPRECISION "
55 "DP_ENT_TRAILEFFECTNUM "
57 "DP_GFX_EXTERNALTEXTURES "
58 "DP_GFX_EXTERNALTEXTURES_PERMAP "
60 "DP_GFX_MODEL_INTERPOLATION "
61 "DP_GFX_QUAKE3MODELTAGS "
65 "DP_GFX_FONTS_FREETYPE "
67 "DP_FONT_VARIABLEWIDTH "
69 "DP_HALFLIFE_MAP_CVAR "
72 "DP_LIGHTSTYLE_STATICVALUE "
76 "DP_MOVETYPEBOUNCEMISSILE "
77 "DP_MOVETYPEFLYWORLDONLY "
80 "DP_QC_ASINACOSATANATAN2TAN "
86 "DP_QC_CVAR_DEFSTRING "
87 "DP_QC_CVAR_DESCRIPTION "
91 "DP_QC_DIGEST_SHA256 "
96 "DP_QC_EXTRESPONSEPACKET "
98 "DP_QC_FINDCHAINFLAGS "
99 "DP_QC_FINDCHAINFLOAT "
100 "DP_QC_FINDCHAIN_TOFIELD "
106 "DP_QC_GETSURFACETRIANGLE "
107 "DP_QC_GETSURFACEPOINTATTRIBUTE "
109 "DP_QC_GETTAGINFO_BONEPROPERTIES "
111 "DP_QC_GETTIME_CDTRACK "
115 "DP_QC_MULTIPLETEMPSTRINGS "
116 "DP_QC_NUM_FOR_EDICT "
118 "DP_QC_SINCOSSQRTPOW "
121 "DP_QC_STRINGBUFFERS "
122 "DP_QC_STRINGBUFFERS_CVARLIST "
123 "DP_QC_STRINGCOLORFUNCTIONS "
124 "DP_QC_STRING_CASE_FUNCTIONS "
126 "DP_QC_TOKENIZEBYSEPARATOR "
127 "DP_QC_TOKENIZE_CONSOLE "
130 "DP_QC_TRACE_MOVETYPE_HITMODEL "
131 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
132 "DP_QC_UNLIMITEDTEMPSTRINGS "
136 "DP_QC_VECTOANGLES_WITH_ROLL "
137 "DP_QC_VECTORVECTORS "
144 "DP_SKELETONOBJECTS "
145 "DP_SND_DIRECTIONLESSATTNNONE "
147 "DP_SND_SOUND7_WIP1 "
148 "DP_SND_SOUND7_WIP2 "
152 "DP_SND_GETSOUNDTIME "
154 "DP_VIDEO_SUBTITLES "
158 "DP_SV_BOUNCEFACTOR "
159 "DP_SV_CLIENTCAMERA "
160 "DP_SV_CLIENTCOLORS "
163 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
164 "DP_SV_DISCARDABLEDEMO "
165 "DP_SV_DRAWONLYTOCLIENT "
168 "DP_SV_ENTITYCONTENTSTRANSITION "
169 "DP_SV_MODELFLAGS_AS_EFFECTS "
170 "DP_SV_MOVETYPESTEP_LANDEVENT "
172 "DP_SV_NODRAWTOCLIENT "
173 "DP_SV_ONENTITYNOSPAWNFUNCTION "
174 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
176 "DP_SV_PING_PACKETLOSS "
177 "DP_SV_PLAYERPHYSICS "
179 "DP_SV_POINTPARTICLES "
181 "DP_SV_PRECACHEANYTIME "
185 "DP_SV_ROTATINGBMODEL "
189 "DP_SV_SPAWNFUNC_PREFIX "
190 "DP_SV_WRITEPICTURE "
191 "DP_SV_WRITEUNTERMINATEDSTRING "
195 "DP_TE_EXPLOSIONRGB "
197 "DP_TE_PARTICLECUBE "
198 "DP_TE_PARTICLERAIN "
199 "DP_TE_PARTICLESNOW "
201 "DP_TE_QUADEFFECTS1 "
204 "DP_TE_STANDARDEFFECTBUILTINS "
205 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
209 "FTE_CSQC_SKELETONOBJECTS "
212 "KRIMZON_SV_PARSECLIENTCOMMAND "
215 "NEXUIZ_PLAYERMODEL "
217 "PRYDON_CLIENTCURSOR "
218 "TENEBRAE_GFX_DLIGHTS "
221 //"EXT_CSQC " // not ready yet
228 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.
230 setorigin (entity, origin)
233 static void VM_SV_setorigin(prvm_prog_t *prog)
238 VM_SAFEPARMCOUNT(2, VM_setorigin);
240 e = PRVM_G_EDICT(OFS_PARM0);
241 if (e == prog->edicts)
243 VM_Warning(prog, "setorigin: can not modify world entity\n");
246 if (e->priv.server->free)
248 VM_Warning(prog, "setorigin: can not modify free entity\n");
251 org = PRVM_G_VECTOR(OFS_PARM1);
252 VectorCopy (org, PRVM_serveredictvector(e, origin));
256 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
257 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qboolean rotate)
261 for (i=0 ; i<3 ; i++)
263 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
265 // set derived values
266 VectorCopy (min, PRVM_serveredictvector(e, mins));
267 VectorCopy (max, PRVM_serveredictvector(e, maxs));
268 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
277 the size box is rotated by the current angle
278 LordHavoc: no it isn't...
280 setsize (entity, minvector, maxvector)
283 static void VM_SV_setsize(prvm_prog_t *prog)
288 VM_SAFEPARMCOUNT(3, VM_setsize);
290 e = PRVM_G_EDICT(OFS_PARM0);
291 if (e == prog->edicts)
293 VM_Warning(prog, "setsize: can not modify world entity\n");
296 if (e->priv.server->free)
298 VM_Warning(prog, "setsize: can not modify free entity\n");
301 min = PRVM_G_VECTOR(OFS_PARM1);
302 max = PRVM_G_VECTOR(OFS_PARM2);
303 SetMinMaxSize(prog, e, min, max, false);
311 setmodel(entity, model)
314 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
315 static void VM_SV_setmodel(prvm_prog_t *prog)
321 VM_SAFEPARMCOUNT(2, VM_setmodel);
323 e = PRVM_G_EDICT(OFS_PARM0);
324 if (e == prog->edicts)
326 VM_Warning(prog, "setmodel: can not modify world entity\n");
329 if (e->priv.server->free)
331 VM_Warning(prog, "setmodel: can not modify free entity\n");
334 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
335 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
336 PRVM_serveredictfloat(e, modelindex) = i;
338 mod = SV_GetModelByIndex(i);
342 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
343 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
345 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
348 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
355 single print to a specific client
357 sprint(clientent, value)
360 static void VM_SV_sprint(prvm_prog_t *prog)
364 char string[VM_STRINGTEMP_LENGTH];
366 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
368 VM_VarString(prog, 1, string, sizeof(string));
370 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
371 // LordHavoc: div0 requested that sprintto world operate like print
378 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
380 VM_Warning(prog, "tried to centerprint to a non-client\n");
384 client = svs.clients + entnum-1;
385 if (!client->netconnection)
388 MSG_WriteChar(&client->netconnection->message,svc_print);
389 MSG_WriteString(&client->netconnection->message, string);
397 single print to a specific client
399 centerprint(clientent, value)
402 static void VM_SV_centerprint(prvm_prog_t *prog)
406 char string[VM_STRINGTEMP_LENGTH];
408 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
410 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
412 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
414 VM_Warning(prog, "tried to centerprint to a non-client\n");
418 client = svs.clients + entnum-1;
419 if (!client->netconnection)
422 VM_VarString(prog, 1, string, sizeof(string));
423 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
424 MSG_WriteString(&client->netconnection->message, string);
431 particle(origin, color, count)
434 static void VM_SV_particle(prvm_prog_t *prog)
440 VM_SAFEPARMCOUNT(4, VM_SV_particle);
442 org = PRVM_G_VECTOR(OFS_PARM0);
443 dir = PRVM_G_VECTOR(OFS_PARM1);
444 color = PRVM_G_FLOAT(OFS_PARM2);
445 count = PRVM_G_FLOAT(OFS_PARM3);
446 SV_StartParticle (org, dir, (int)color, (int)count);
456 static void VM_SV_ambientsound(prvm_prog_t *prog)
460 float vol, attenuation;
463 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
465 pos = PRVM_G_VECTOR (OFS_PARM0);
466 samp = PRVM_G_STRING(OFS_PARM1);
467 vol = PRVM_G_FLOAT(OFS_PARM2);
468 attenuation = PRVM_G_FLOAT(OFS_PARM3);
470 // check to see if samp was properly precached
471 soundnum = SV_SoundIndex(samp, 1);
479 // add an svc_spawnambient command to the level signon packet
482 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
484 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
486 MSG_WriteVector(&sv.signon, pos, sv.protocol);
488 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
489 MSG_WriteShort (&sv.signon, soundnum);
491 MSG_WriteByte (&sv.signon, soundnum);
493 MSG_WriteByte (&sv.signon, (int)(vol*255));
494 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
502 Each entity can have eight independant sound sources, like voice,
505 Channel 0 is an auto-allocate channel, the others override anything
506 already running on that entity/channel pair.
508 An attenuation of 0 will play full volume everywhere in the level.
509 Larger attenuations will drop off.
513 static void VM_SV_sound(prvm_prog_t *prog)
517 prvm_edict_t *entity;
523 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
525 entity = PRVM_G_EDICT(OFS_PARM0);
526 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
527 sample = PRVM_G_STRING(OFS_PARM2);
528 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
531 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
535 attenuation = PRVM_G_FLOAT(OFS_PARM4);
539 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
544 if(channel >= 8 && channel <= 15) // weird QW feature
546 flags |= CHANFLAG_RELIABLE;
551 flags = PRVM_G_FLOAT(OFS_PARM6);
553 if (volume < 0 || volume > 255)
555 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
559 if (attenuation < 0 || attenuation > 4)
561 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
565 channel = CHAN_USER2ENGINE(channel);
567 if (!IS_CHAN(channel))
569 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
573 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE, pitchchange);
580 Follows the same logic as VM_SV_sound, except instead of
581 an entity, an origin for the sound is provided, and channel
582 is omitted (since no entity is being tracked).
586 static void VM_SV_pointsound(prvm_prog_t *prog)
594 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
596 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
597 sample = PRVM_G_STRING(OFS_PARM1);
598 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
599 attenuation = PRVM_G_FLOAT(OFS_PARM3);
600 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
602 if (volume < 0 || volume > 255)
604 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
608 if (attenuation < 0 || attenuation > 4)
610 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
614 SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
621 Used for use tracing and shot targeting
622 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
623 if the tryents flag is set.
625 traceline (vector1, vector2, movetype, ignore)
628 static void VM_SV_traceline(prvm_prog_t *prog)
635 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
637 prog->xfunction->builtinsprofile += 30;
639 v1 = PRVM_G_VECTOR(OFS_PARM0);
640 v2 = PRVM_G_VECTOR(OFS_PARM1);
641 move = (int)PRVM_G_FLOAT(OFS_PARM2);
642 ent = PRVM_G_EDICT(OFS_PARM3);
644 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]))
645 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));
647 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
649 VM_SetTraceGlobals(prog, &trace);
657 Used for use tracing and shot targeting
658 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
659 if the tryents flag is set.
661 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
664 // LordHavoc: added this for my own use, VERY useful, similar to traceline
665 static void VM_SV_tracebox(prvm_prog_t *prog)
667 float *v1, *v2, *m1, *m2;
672 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
674 prog->xfunction->builtinsprofile += 30;
676 v1 = PRVM_G_VECTOR(OFS_PARM0);
677 m1 = PRVM_G_VECTOR(OFS_PARM1);
678 m2 = PRVM_G_VECTOR(OFS_PARM2);
679 v2 = PRVM_G_VECTOR(OFS_PARM3);
680 move = (int)PRVM_G_FLOAT(OFS_PARM4);
681 ent = PRVM_G_EDICT(OFS_PARM5);
683 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]))
684 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));
686 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
688 VM_SetTraceGlobals(prog, &trace);
691 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
696 vec3_t original_origin;
697 vec3_t original_velocity;
698 vec3_t original_angles;
699 vec3_t original_avelocity;
702 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
703 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
704 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
705 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
707 gravity = PRVM_serveredictfloat(tossent, gravity);
710 gravity *= sv_gravity.value * 0.025;
712 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
714 SV_CheckVelocity (tossent);
715 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
716 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
717 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
718 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
719 trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
720 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
721 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
723 if (trace.fraction < 1)
727 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
728 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
729 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
730 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
735 static void VM_SV_tracetoss(prvm_prog_t *prog)
739 prvm_edict_t *ignore;
741 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
743 prog->xfunction->builtinsprofile += 600;
745 ent = PRVM_G_EDICT(OFS_PARM0);
746 if (ent == prog->edicts)
748 VM_Warning(prog, "tracetoss: can not use world entity\n");
751 ignore = PRVM_G_EDICT(OFS_PARM1);
753 trace = SV_Trace_Toss(prog, ent, ignore);
755 VM_SetTraceGlobals(prog, &trace);
758 //============================================================================
760 static int checkpvsbytes;
761 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
763 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
769 // cycle to the next one
771 check = bound(1, check, svs.maxclients);
772 if (check == svs.maxclients)
780 prog->xfunction->builtinsprofile++;
782 if (i == svs.maxclients+1)
784 // look up the client's edict
785 ent = PRVM_EDICT_NUM(i);
786 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
787 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
789 // found a valid client (possibly the same one again)
793 // get the PVS for the entity
794 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
796 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
797 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
806 Returns a client (or object that has a client enemy) that would be a
809 If there is more than one valid option, they are cycled each frame
811 If (self.origin + self.viewofs) is not in the PVS of the current target,
812 it is not returned at all.
817 int c_invis, c_notvis;
818 static void VM_SV_checkclient(prvm_prog_t *prog)
820 prvm_edict_t *ent, *self;
823 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
825 // find a new check if on a new frame
826 if (sv.time - sv.lastchecktime >= 0.1)
828 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
829 sv.lastchecktime = sv.time;
832 // return check if it might be visible
833 ent = PRVM_EDICT_NUM(sv.lastcheck);
834 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
836 VM_RETURN_EDICT(prog->edicts);
840 // if current entity can't possibly see the check entity, return 0
841 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
842 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
843 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
846 VM_RETURN_EDICT(prog->edicts);
850 // might be able to see it
852 VM_RETURN_EDICT(ent);
855 //============================================================================
861 Checks if an entity is in a point's PVS.
862 Should be fast but can be inexact.
864 float checkpvs(vector viewpos, entity viewee) = #240;
867 static void VM_SV_checkpvs(prvm_prog_t *prog)
870 prvm_edict_t *viewee;
875 unsigned char fatpvs[MAX_MAP_LEAFS/8];
878 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
879 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
880 viewee = PRVM_G_EDICT(OFS_PARM1);
882 if(viewee->priv.server->free)
884 VM_Warning(prog, "checkpvs: can not check free entity\n");
885 PRVM_G_FLOAT(OFS_RETURN) = 4;
890 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
892 // no PVS support on this worldmodel... darn
893 PRVM_G_FLOAT(OFS_RETURN) = 3;
896 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
899 // viewpos isn't in any PVS... darn
900 PRVM_G_FLOAT(OFS_RETURN) = 2;
903 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
905 // using fat PVS like FTEQW does (slow)
906 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
908 // no PVS support on this worldmodel... darn
909 PRVM_G_FLOAT(OFS_RETURN) = 3;
912 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
915 // viewpos isn't in any PVS... darn
916 PRVM_G_FLOAT(OFS_RETURN) = 2;
919 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
928 Sends text over to the client's execution buffer
930 stuffcmd (clientent, value, ...)
933 static void VM_SV_stuffcmd(prvm_prog_t *prog)
937 char string[VM_STRINGTEMP_LENGTH];
939 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
941 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
942 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
944 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
948 VM_VarString(prog, 1, string, sizeof(string));
951 host_client = svs.clients + entnum-1;
952 Host_ClientCommands ("%s", string);
960 Returns a chain of entities that have origins within a spherical area
962 findradius (origin, radius)
965 static void VM_SV_findradius(prvm_prog_t *prog)
967 prvm_edict_t *ent, *chain;
968 vec_t radius, radius2;
969 vec3_t org, eorg, mins, maxs;
972 static prvm_edict_t *touchedicts[MAX_EDICTS];
975 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
978 chainfield = PRVM_G_INT(OFS_PARM2);
980 chainfield = prog->fieldoffsets.chain;
982 prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
984 chain = (prvm_edict_t *)prog->edicts;
986 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
987 radius = PRVM_G_FLOAT(OFS_PARM1);
988 radius2 = radius * radius;
990 mins[0] = org[0] - (radius + 1);
991 mins[1] = org[1] - (radius + 1);
992 mins[2] = org[2] - (radius + 1);
993 maxs[0] = org[0] + (radius + 1);
994 maxs[1] = org[1] + (radius + 1);
995 maxs[2] = org[2] + (radius + 1);
996 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
997 if (numtouchedicts > MAX_EDICTS)
999 // this never happens
1000 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1001 numtouchedicts = MAX_EDICTS;
1003 for (i = 0;i < numtouchedicts;i++)
1005 ent = touchedicts[i];
1006 prog->xfunction->builtinsprofile++;
1007 // Quake did not return non-solid entities but darkplaces does
1008 // (note: this is the reason you can't blow up fallen zombies)
1009 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1011 // LordHavoc: compare against bounding box rather than center so it
1012 // doesn't miss large objects, and use DotProduct instead of Length
1013 // for a major speedup
1014 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1015 if (sv_gameplayfix_findradiusdistancetobox.integer)
1017 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1018 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1019 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1022 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1023 if (DotProduct(eorg, eorg) < radius2)
1025 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1030 VM_RETURN_EDICT(chain);
1033 static void VM_SV_precache_sound(prvm_prog_t *prog)
1035 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1036 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1039 static void VM_SV_precache_model(prvm_prog_t *prog)
1041 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1042 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1043 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1050 float(float yaw, float dist[, settrace]) walkmove
1053 static void VM_SV_walkmove(prvm_prog_t *prog)
1062 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1064 // assume failure if it returns early
1065 PRVM_G_FLOAT(OFS_RETURN) = 0;
1067 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1068 if (ent == prog->edicts)
1070 VM_Warning(prog, "walkmove: can not modify world entity\n");
1073 if (ent->priv.server->free)
1075 VM_Warning(prog, "walkmove: can not modify free entity\n");
1078 yaw = PRVM_G_FLOAT(OFS_PARM0);
1079 dist = PRVM_G_FLOAT(OFS_PARM1);
1080 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1082 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1085 yaw = yaw*M_PI*2 / 360;
1087 move[0] = cos(yaw)*dist;
1088 move[1] = sin(yaw)*dist;
1091 // save program state, because SV_movestep may call other progs
1092 oldf = prog->xfunction;
1093 oldself = PRVM_serverglobaledict(self);
1095 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1098 // restore program state
1099 prog->xfunction = oldf;
1100 PRVM_serverglobaledict(self) = oldself;
1111 static void VM_SV_droptofloor(prvm_prog_t *prog)
1117 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1119 // assume failure if it returns early
1120 PRVM_G_FLOAT(OFS_RETURN) = 0;
1122 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1123 if (ent == prog->edicts)
1125 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1128 if (ent->priv.server->free)
1130 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1134 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1137 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1138 if (sv_gameplayfix_unstickentities.integer)
1139 SV_UnstickEntity(ent);
1141 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1142 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1145 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]);
1146 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1147 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1148 VectorSubtract(trace.endpos, offset, trace.endpos);
1149 if (trace.startsolid)
1151 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]);
1152 if (sv_gameplayfix_unstickentities.integer)
1153 SV_UnstickEntity(ent);
1155 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1156 PRVM_serveredictedict(ent, groundentity) = 0;
1157 PRVM_G_FLOAT(OFS_RETURN) = 1;
1159 else if (trace.fraction < 1)
1161 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]);
1162 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1163 if (sv_gameplayfix_unstickentities.integer)
1164 SV_UnstickEntity(ent);
1166 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1167 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1168 PRVM_G_FLOAT(OFS_RETURN) = 1;
1169 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1170 ent->priv.server->suspendedinairflag = true;
1175 if (trace.fraction != 1)
1177 if (trace.fraction < 1)
1178 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1180 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1181 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1182 PRVM_G_FLOAT(OFS_RETURN) = 1;
1183 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1184 ent->priv.server->suspendedinairflag = true;
1193 void(float style, string value) lightstyle
1196 static void VM_SV_lightstyle(prvm_prog_t *prog)
1203 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1205 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1206 val = PRVM_G_STRING(OFS_PARM1);
1208 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1209 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1212 // change the string in sv
1213 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1215 // send message to all clients on this server
1216 if (sv.state != ss_active)
1219 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1221 if (client->active && client->netconnection)
1223 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1224 MSG_WriteChar (&client->netconnection->message,style);
1225 MSG_WriteString (&client->netconnection->message, val);
1235 static void VM_SV_checkbottom(prvm_prog_t *prog)
1237 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1238 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1246 static void VM_SV_pointcontents(prvm_prog_t *prog)
1248 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1249 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1256 Pick a vector for the player to shoot along
1257 vector aim(entity, missilespeed)
1260 static void VM_SV_aim(prvm_prog_t *prog)
1262 prvm_edict_t *ent, *check, *bestent;
1263 vec3_t start, dir, end, bestdir;
1266 float dist, bestdist;
1269 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1271 // assume failure if it returns early
1272 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1273 // if sv_aim is so high it can't possibly accept anything, skip out early
1274 if (sv_aim.value >= 1)
1277 ent = PRVM_G_EDICT(OFS_PARM0);
1278 if (ent == prog->edicts)
1280 VM_Warning(prog, "aim: can not use world entity\n");
1283 if (ent->priv.server->free)
1285 VM_Warning(prog, "aim: can not use free entity\n");
1288 //speed = PRVM_G_FLOAT(OFS_PARM1);
1290 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1293 // try sending a trace straight
1294 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1295 VectorMA (start, 2048, dir, end);
1296 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1297 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1298 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1300 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1305 // try all possible entities
1306 VectorCopy (dir, bestdir);
1307 bestdist = sv_aim.value;
1310 check = PRVM_NEXT_EDICT(prog->edicts);
1311 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1313 prog->xfunction->builtinsprofile++;
1314 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1318 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1319 continue; // don't aim at teammate
1320 for (j=0 ; j<3 ; j++)
1321 end[j] = PRVM_serveredictvector(check, origin)[j]
1322 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1323 VectorSubtract (end, start, dir);
1324 VectorNormalize (dir);
1325 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1326 if (dist < bestdist)
1327 continue; // to far to turn
1328 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1329 if (tr.ent == check)
1330 { // can shoot at this one
1338 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1339 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1340 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1342 VectorNormalize (end);
1343 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1347 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1352 ===============================================================================
1356 ===============================================================================
1359 #define MSG_BROADCAST 0 // unreliable to all
1360 #define MSG_ONE 1 // reliable to one (msg_entity)
1361 #define MSG_ALL 2 // reliable to all
1362 #define MSG_INIT 3 // write to the init string
1363 #define MSG_ENTITY 5
1365 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1371 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1375 return &sv.datagram;
1378 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1379 entnum = PRVM_NUM_FOR_EDICT(ent);
1380 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1382 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1383 return &sv.reliable_datagram;
1386 return &svs.clients[entnum-1].netconnection->message;
1389 VM_Warning(prog, "WriteDest: bad destination\n");
1391 return &sv.reliable_datagram;
1397 return sv.writeentitiestoclient_msg;
1403 static void VM_SV_WriteByte(prvm_prog_t *prog)
1405 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1406 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1409 static void VM_SV_WriteChar(prvm_prog_t *prog)
1411 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1412 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1415 static void VM_SV_WriteShort(prvm_prog_t *prog)
1417 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1418 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1421 static void VM_SV_WriteLong(prvm_prog_t *prog)
1423 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1424 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1427 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1429 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1430 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1433 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1435 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1436 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1439 static void VM_SV_WriteString(prvm_prog_t *prog)
1441 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1442 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1445 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1447 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1448 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1452 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1454 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1455 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1458 // writes a picture as at most size bytes of data
1460 // IMGNAME \0 SIZE(short) IMGDATA
1461 // if failed to read/compress:
1463 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1464 static void VM_SV_WritePicture(prvm_prog_t *prog)
1466 const char *imgname;
1470 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1472 imgname = PRVM_G_STRING(OFS_PARM1);
1473 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1477 MSG_WriteString(WriteDest(prog), imgname);
1478 if(Image_Compress(imgname, size, &buf, &size))
1481 MSG_WriteShort(WriteDest(prog), size);
1482 SZ_Write(WriteDest(prog), (unsigned char *) buf, size);
1487 MSG_WriteShort(WriteDest(prog), 0);
1491 //////////////////////////////////////////////////////////
1493 static void VM_SV_makestatic(prvm_prog_t *prog)
1498 // allow 0 parameters due to an id1 qc bug in which this function is used
1499 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1500 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1502 if (prog->argc >= 1)
1503 ent = PRVM_G_EDICT(OFS_PARM0);
1505 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1506 if (ent == prog->edicts)
1508 VM_Warning(prog, "makestatic: can not modify world entity\n");
1511 if (ent->priv.server->free)
1513 VM_Warning(prog, "makestatic: can not modify free entity\n");
1518 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1523 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1524 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1525 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1527 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1529 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1530 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1531 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1535 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1536 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1537 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1540 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1541 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1542 for (i=0 ; i<3 ; i++)
1544 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1545 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1548 // throw the entity away now
1549 PRVM_ED_Free(prog, ent);
1552 //=============================================================================
1559 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1565 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1567 ent = PRVM_G_EDICT(OFS_PARM0);
1568 i = PRVM_NUM_FOR_EDICT(ent);
1569 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1571 Con_Print("tried to setspawnparms on a non-client\n");
1575 // copy spawn parms out of the client_t
1576 client = svs.clients + i-1;
1577 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1578 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1585 Returns a color vector indicating the lighting at the requested point.
1587 (Internal Operation note: actually measures the light beneath the point, just like
1588 the model lighting on the client)
1593 static void VM_SV_getlight(prvm_prog_t *prog)
1595 vec3_t ambientcolor, diffusecolor, diffusenormal;
1597 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1598 p = PRVM_G_VECTOR(OFS_PARM0);
1599 VectorClear(ambientcolor);
1600 VectorClear(diffusecolor);
1601 VectorClear(diffusenormal);
1602 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1603 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1604 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1609 unsigned char type; // 1/2/8 or other value if isn't used
1613 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1614 static int vm_customstats_last;
1616 void VM_CustomStats_Clear (void)
1620 Z_Free(vm_customstats);
1621 vm_customstats = NULL;
1622 vm_customstats_last = -1;
1626 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1628 prvm_prog_t *prog = SVVM_prog;
1635 for(i=0; i<vm_customstats_last+1 ;i++)
1637 if(!vm_customstats[i].type)
1639 switch(vm_customstats[i].type)
1641 //string as 16 bytes
1644 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1645 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1646 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1647 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1648 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1650 //float field sent as-is
1652 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1654 //integer value of float field
1656 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1664 // void(float index, float type, .void field) SV_AddStat = #232;
1665 // Set up an auto-sent player stat.
1666 // Client's get thier own fields sent to them. Index may not be less than 32.
1667 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1668 // 1: string (4 stats carrying a total of 16 charactures)
1669 // 2: float (one stat, float converted to an integer for transportation)
1670 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1671 static void VM_SV_AddStat(prvm_prog_t *prog)
1676 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1680 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1683 VM_Warning(prog, "PF_SV_AddStat: not enough memory\n");
1687 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1688 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1689 off = PRVM_G_INT (OFS_PARM2);
1694 VM_Warning(prog, "PF_SV_AddStat: index may not be less than 32\n");
1697 if(i >= (MAX_CL_STATS-32))
1699 VM_Warning(prog, "PF_SV_AddStat: index >= MAX_CL_STATS\n");
1702 if(i > (MAX_CL_STATS-32-4) && type == 1)
1704 VM_Warning(prog, "PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1707 vm_customstats[i].type = type;
1708 vm_customstats[i].fieldoffset = off;
1709 if(vm_customstats_last < i)
1710 vm_customstats_last = i;
1717 copies data from one entity to another
1719 copyentity(src, dst)
1722 static void VM_SV_copyentity(prvm_prog_t *prog)
1724 prvm_edict_t *in, *out;
1725 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1726 in = PRVM_G_EDICT(OFS_PARM0);
1727 if (in == prog->edicts)
1729 VM_Warning(prog, "copyentity: can not read world entity\n");
1732 if (in->priv.server->free)
1734 VM_Warning(prog, "copyentity: can not read free entity\n");
1737 out = PRVM_G_EDICT(OFS_PARM1);
1738 if (out == prog->edicts)
1740 VM_Warning(prog, "copyentity: can not modify world entity\n");
1743 if (out->priv.server->free)
1745 VM_Warning(prog, "copyentity: can not modify free entity\n");
1748 memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
1757 sets the color of a client and broadcasts the update to all connected clients
1759 setcolor(clientent, value)
1762 static void VM_SV_setcolor(prvm_prog_t *prog)
1767 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1768 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1769 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1771 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1773 Con_Print("tried to setcolor a non-client\n");
1777 client = svs.clients + entnum-1;
1780 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1781 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1784 if (client->old_colors != client->colors)
1786 client->old_colors = client->colors;
1787 // send notification to all clients
1788 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1789 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1790 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1798 effect(origin, modelname, startframe, framecount, framerate)
1801 static void VM_SV_effect(prvm_prog_t *prog)
1805 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1806 s = PRVM_G_STRING(OFS_PARM1);
1809 VM_Warning(prog, "effect: no model specified\n");
1813 i = SV_ModelIndex(s, 1);
1816 VM_Warning(prog, "effect: model not precached\n");
1820 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1822 VM_Warning(prog, "effect: framecount < 1\n");
1826 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1828 VM_Warning(prog, "effect: framerate < 1\n");
1832 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));
1835 static void VM_SV_te_blood(prvm_prog_t *prog)
1837 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1838 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1840 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1841 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1843 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1844 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1845 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1847 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1848 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1849 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1851 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1852 SV_FlushBroadcastMessages();
1855 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1857 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1858 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1860 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1861 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1863 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1864 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1865 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1868 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1869 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1873 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1874 SV_FlushBroadcastMessages();
1877 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1879 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1880 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1881 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1883 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1884 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1885 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1887 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1888 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1889 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1890 SV_FlushBroadcastMessages();
1893 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1895 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1896 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1898 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1899 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1911 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1913 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1915 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1916 // gravity true/false
1917 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1919 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1920 SV_FlushBroadcastMessages();
1923 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1925 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1926 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1928 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1929 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1936 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1941 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1943 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1945 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1946 SV_FlushBroadcastMessages();
1949 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1951 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1952 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1954 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1955 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1965 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1969 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1971 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1972 SV_FlushBroadcastMessages();
1975 static void VM_SV_te_spark(prvm_prog_t *prog)
1977 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1978 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1980 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1981 MSG_WriteByte(&sv.datagram, TE_SPARK);
1983 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1984 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1985 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1987 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1988 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1989 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1991 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1992 SV_FlushBroadcastMessages();
1995 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
1997 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1998 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1999 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2001 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2002 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2004 SV_FlushBroadcastMessages();
2007 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2009 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2010 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2011 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2014 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2015 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2016 SV_FlushBroadcastMessages();
2019 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2021 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2022 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2023 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2025 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2026 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2028 SV_FlushBroadcastMessages();
2031 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2033 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2034 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2035 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2037 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2038 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2039 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2040 SV_FlushBroadcastMessages();
2043 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2045 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2046 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2047 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2049 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2050 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2052 SV_FlushBroadcastMessages();
2055 static void VM_SV_te_customflash(prvm_prog_t *prog)
2057 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2058 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2060 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2061 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2063 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2064 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2065 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2067 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2069 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2071 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2072 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2073 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2074 SV_FlushBroadcastMessages();
2077 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2079 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2080 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2081 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2083 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2084 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2085 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2086 SV_FlushBroadcastMessages();
2089 static void VM_SV_te_spike(prvm_prog_t *prog)
2091 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2092 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2093 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2095 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2096 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2097 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2098 SV_FlushBroadcastMessages();
2101 static void VM_SV_te_superspike(prvm_prog_t *prog)
2103 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2104 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2105 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2107 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2108 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2109 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2110 SV_FlushBroadcastMessages();
2113 static void VM_SV_te_explosion(prvm_prog_t *prog)
2115 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2116 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2117 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2119 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2120 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2121 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2122 SV_FlushBroadcastMessages();
2125 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2127 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2128 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2129 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2131 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2132 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2133 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2134 SV_FlushBroadcastMessages();
2137 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2139 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2140 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2141 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2143 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2144 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2145 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2146 SV_FlushBroadcastMessages();
2149 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2151 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2152 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2153 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2155 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2156 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2157 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2158 SV_FlushBroadcastMessages();
2161 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2163 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2164 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2165 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2167 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2168 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2169 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2170 SV_FlushBroadcastMessages();
2173 static void VM_SV_te_teleport(prvm_prog_t *prog)
2175 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2176 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2177 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2179 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2180 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2181 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2182 SV_FlushBroadcastMessages();
2185 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2187 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2188 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2189 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2191 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2192 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2193 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2195 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2196 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2197 SV_FlushBroadcastMessages();
2200 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2202 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2203 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2204 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2206 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2208 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2209 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2210 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2212 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2213 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2214 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2215 SV_FlushBroadcastMessages();
2218 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2220 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2221 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2222 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2224 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2226 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2227 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2230 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2231 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2232 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2233 SV_FlushBroadcastMessages();
2236 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2238 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2239 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2240 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2242 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2244 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2245 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2246 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2248 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2249 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2250 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2251 SV_FlushBroadcastMessages();
2254 static void VM_SV_te_beam(prvm_prog_t *prog)
2256 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2257 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2258 MSG_WriteByte(&sv.datagram, TE_BEAM);
2260 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2262 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2263 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2264 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2266 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2267 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2268 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2269 SV_FlushBroadcastMessages();
2272 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2274 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2275 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2276 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2277 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2278 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2279 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2280 SV_FlushBroadcastMessages();
2283 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2285 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2286 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2287 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2289 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2290 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2291 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2293 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2294 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2295 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2297 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2298 SV_FlushBroadcastMessages();
2301 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2302 //this function originally written by KrimZon, made shorter by LordHavoc
2303 static void VM_SV_clientcommand(prvm_prog_t *prog)
2305 client_t *temp_client;
2307 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2309 //find client for this entity
2310 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2311 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2313 Con_Print("PF_clientcommand: entity is not a client\n");
2317 temp_client = host_client;
2318 host_client = svs.clients + i;
2319 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
2320 host_client = temp_client;
2323 //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)
2324 static void VM_SV_setattachment(prvm_prog_t *prog)
2326 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2327 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2328 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2331 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2333 if (e == prog->edicts)
2335 VM_Warning(prog, "setattachment: can not modify world entity\n");
2338 if (e->priv.server->free)
2340 VM_Warning(prog, "setattachment: can not modify free entity\n");
2344 if (tagentity == NULL)
2345 tagentity = prog->edicts;
2349 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2351 model = SV_GetModelFromEdict(tagentity);
2354 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2356 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);
2359 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));
2362 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2363 PRVM_serveredictfloat(e, tag_index) = tagindex;
2366 /////////////////////////////////////////
2367 // DP_MD3_TAGINFO extension coded by VorteX
2369 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2373 i = (int)PRVM_serveredictfloat(e, modelindex);
2374 if (i < 1 || i >= MAX_MODELS)
2377 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2380 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2387 Matrix4x4_CreateIdentity(tag_localmatrix);
2389 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2391 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2402 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2405 float pitchsign = 1;
2407 scale = PRVM_serveredictfloat(ent, scale);
2412 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);
2415 pitchsign = SV_GetPitchSign(prog, ent);
2416 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);
2420 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2423 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2425 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2426 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2427 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2428 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2430 *out = identitymatrix;
2434 // Warnings/errors code:
2435 // 0 - normal (everything all-right)
2438 // 3 - null or non-precached model
2439 // 4 - no tags with requested index
2440 // 5 - runaway loop at attachment chain
2441 extern cvar_t cl_bob;
2442 extern cvar_t cl_bobcycle;
2443 extern cvar_t cl_bobup;
2444 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2447 int modelindex, attachloop;
2448 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2451 *out = identitymatrix; // warnings and errors return identical matrix
2453 if (ent == prog->edicts)
2455 if (ent->priv.server->free)
2458 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2459 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2462 model = SV_GetModelByIndex(modelindex);
2464 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2465 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2466 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2468 tagmatrix = identitymatrix;
2469 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2473 if (attachloop >= 256) // prevent runaway looping
2475 // apply transformation by child's tagindex on parent entity and then
2476 // by parent entity itself
2477 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2478 if (ret && attachloop == 0)
2480 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2481 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2482 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2483 // next iteration we process the parent entity
2484 if (PRVM_serveredictedict(ent, tag_entity))
2486 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2487 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2494 // RENDER_VIEWMODEL magic
2495 if (PRVM_serveredictedict(ent, viewmodelforclient))
2497 Matrix4x4_Copy(&tagmatrix, out);
2498 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2500 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2501 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2504 // Cl_bob, ported from rendering code
2505 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2508 // LordHavoc: this code is *weird*, but not replacable (I think it
2509 // should be done in QC on the server, but oh well, quake is quake)
2510 // LordHavoc: figured out bobup: the time at which the sin is at 180
2511 // degrees (which allows lengthening or squishing the peak or valley)
2512 cycle = sv.time/cl_bobcycle.value;
2513 cycle -= (int)cycle;
2514 if (cycle < cl_bobup.value)
2515 cycle = sin(M_PI * cycle / cl_bobup.value);
2517 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2518 // bob is proportional to velocity in the xy plane
2519 // (don't count Z, or jumping messes it up)
2520 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;
2521 bob = bob*0.3 + bob*0.7*cycle;
2522 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2529 //float(entity ent, string tagname) gettagindex;
2531 static void VM_SV_gettagindex(prvm_prog_t *prog)
2534 const char *tag_name;
2537 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2539 ent = PRVM_G_EDICT(OFS_PARM0);
2540 tag_name = PRVM_G_STRING(OFS_PARM1);
2542 if (ent == prog->edicts)
2544 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2547 if (ent->priv.server->free)
2549 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2554 if (!SV_GetModelFromEdict(ent))
2555 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2558 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2560 if(developer_extra.integer)
2561 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2563 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2566 //vector(entity ent, float tagindex) gettaginfo;
2567 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2571 matrix4x4_t tag_matrix;
2572 matrix4x4_t tag_localmatrix;
2574 const char *tagname;
2576 vec3_t fo, le, up, trans;
2577 const dp_model_t *model;
2579 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2581 e = PRVM_G_EDICT(OFS_PARM0);
2582 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2584 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2585 Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
2586 VectorScale(le, -1, PRVM_serverglobalvector(v_right));
2587 model = SV_GetModelFromEdict(e);
2588 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2589 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
2590 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2591 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2592 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2594 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2595 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2596 VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
2597 VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
2598 VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
2599 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2604 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2607 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2610 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2613 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2616 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2621 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2622 static void VM_SV_dropclient(prvm_prog_t *prog)
2625 client_t *oldhostclient;
2626 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2627 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2628 if (clientnum < 0 || clientnum >= svs.maxclients)
2630 VM_Warning(prog, "dropclient: not a client\n");
2633 if (!svs.clients[clientnum].active)
2635 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2638 oldhostclient = host_client;
2639 host_client = svs.clients + clientnum;
2640 SV_DropClient(false);
2641 host_client = oldhostclient;
2644 //entity() spawnclient (DP_SV_BOTCLIENT)
2645 static void VM_SV_spawnclient(prvm_prog_t *prog)
2649 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2650 prog->xfunction->builtinsprofile += 2;
2652 for (i = 0;i < svs.maxclients;i++)
2654 if (!svs.clients[i].active)
2656 prog->xfunction->builtinsprofile += 100;
2657 SV_ConnectClient (i, NULL);
2658 // this has to be set or else ClientDisconnect won't be called
2659 // we assume the qc will call ClientConnect...
2660 svs.clients[i].clientconnectcalled = true;
2661 ed = PRVM_EDICT_NUM(i + 1);
2665 VM_RETURN_EDICT(ed);
2668 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2669 static void VM_SV_clienttype(prvm_prog_t *prog)
2672 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2673 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2674 if (clientnum < 0 || clientnum >= svs.maxclients)
2675 PRVM_G_FLOAT(OFS_RETURN) = 3;
2676 else if (!svs.clients[clientnum].active)
2677 PRVM_G_FLOAT(OFS_RETURN) = 0;
2678 else if (svs.clients[clientnum].netconnection)
2679 PRVM_G_FLOAT(OFS_RETURN) = 1;
2681 PRVM_G_FLOAT(OFS_RETURN) = 2;
2688 string(string key) serverkey
2691 static void VM_SV_serverkey(prvm_prog_t *prog)
2693 char string[VM_STRINGTEMP_LENGTH];
2694 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2695 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2696 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2699 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2700 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2705 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2707 e = PRVM_G_EDICT(OFS_PARM0);
2708 if (e == prog->edicts)
2710 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2713 if (e->priv.server->free)
2715 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2718 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2719 if (i <= 0 || i >= MAX_MODELS)
2721 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2724 if (!sv.model_precache[i][0])
2726 VM_Warning(prog, "setmodelindex: model not precached\n");
2730 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2731 PRVM_serveredictfloat(e, modelindex) = i;
2733 mod = SV_GetModelByIndex(i);
2737 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2738 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2740 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2743 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2746 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2747 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2750 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2752 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2754 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2755 if (i <= 0 || i >= MAX_MODELS)
2757 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2760 if (!sv.model_precache[i][0])
2762 VM_Warning(prog, "modelnameforindex: model not precached\n");
2766 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2769 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2770 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2773 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2774 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2777 PRVM_G_FLOAT(OFS_RETURN) = i;
2780 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2781 static void VM_SV_trailparticles(prvm_prog_t *prog)
2783 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2785 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2788 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2789 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2790 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2791 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2792 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2793 SV_FlushBroadcastMessages();
2796 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2797 static void VM_SV_pointparticles(prvm_prog_t *prog)
2799 int effectnum, count;
2801 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2803 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2806 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2807 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2808 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2809 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2810 if (count == 1 && !VectorLength2(vel))
2813 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2814 MSG_WriteShort(&sv.datagram, effectnum);
2815 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2819 // 1+2+12+12+2=29 bytes
2820 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2821 MSG_WriteShort(&sv.datagram, effectnum);
2822 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2823 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2824 MSG_WriteShort(&sv.datagram, count);
2827 SV_FlushBroadcastMessages();
2830 //PF_setpause, // void(float pause) setpause = #531;
2831 static void VM_SV_setpause(prvm_prog_t *prog) {
2833 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2834 if (pauseValue != 0) { //pause the game
2836 sv.pausedstart = realtime;
2837 } else { //disable pause, in case it was enabled
2838 if (sv.paused != 0) {
2843 // send notification to all clients
2844 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2845 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2848 // #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.
2849 static void VM_SV_skel_create(prvm_prog_t *prog)
2851 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2852 dp_model_t *model = SV_GetModelByIndex(modelindex);
2853 skeleton_t *skeleton;
2855 PRVM_G_FLOAT(OFS_RETURN) = 0;
2856 if (!model || !model->num_bones)
2858 for (i = 0;i < MAX_EDICTS;i++)
2859 if (!prog->skeletons[i])
2861 if (i == MAX_EDICTS)
2863 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2864 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2865 skeleton->model = model;
2866 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2867 // initialize to identity matrices
2868 for (i = 0;i < skeleton->model->num_bones;i++)
2869 skeleton->relativetransforms[i] = identitymatrix;
2872 // #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
2873 static void VM_SV_skel_build(prvm_prog_t *prog)
2875 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2876 skeleton_t *skeleton;
2877 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2878 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2879 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2880 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2881 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2882 dp_model_t *model = SV_GetModelByIndex(modelindex);
2887 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2888 frameblend_t frameblend[MAX_FRAMEBLENDS];
2889 matrix4x4_t blendedmatrix;
2891 PRVM_G_FLOAT(OFS_RETURN) = 0;
2892 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2894 firstbone = max(0, firstbone);
2895 lastbone = min(lastbone, model->num_bones - 1);
2896 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2897 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2898 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
2899 blendfrac = 1.0f - retainfrac;
2900 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2901 frameblend[numblends].lerp *= blendfrac;
2902 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2904 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2905 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2906 for (blendindex = 0;blendindex < numblends;blendindex++)
2908 Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2909 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2911 skeleton->relativetransforms[bonenum] = blendedmatrix;
2913 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2916 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2917 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
2919 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2920 skeleton_t *skeleton;
2921 PRVM_G_FLOAT(OFS_RETURN) = 0;
2922 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2924 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2927 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2928 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
2930 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2931 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2932 skeleton_t *skeleton;
2933 PRVM_G_INT(OFS_RETURN) = 0;
2934 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2936 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2938 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
2941 // #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)
2942 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
2944 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2945 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2946 skeleton_t *skeleton;
2947 PRVM_G_FLOAT(OFS_RETURN) = 0;
2948 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2950 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2952 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2955 // #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
2956 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
2958 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2959 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2960 skeleton_t *skeleton;
2961 PRVM_G_FLOAT(OFS_RETURN) = 0;
2962 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2964 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2967 // #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)
2968 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
2970 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2971 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2972 skeleton_t *skeleton;
2974 vec3_t forward, left, up, origin;
2975 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2976 VectorClear(PRVM_clientglobalvector(v_forward));
2977 VectorClear(PRVM_clientglobalvector(v_right));
2978 VectorClear(PRVM_clientglobalvector(v_up));
2979 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2981 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2983 matrix = skeleton->relativetransforms[bonenum];
2984 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2985 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2986 VectorNegate(left, PRVM_clientglobalvector(v_right));
2987 VectorCopy(up, PRVM_clientglobalvector(v_up));
2988 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2991 // #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)
2992 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
2994 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2995 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2996 skeleton_t *skeleton;
2999 vec3_t forward, left, up, origin;
3000 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3001 VectorClear(PRVM_clientglobalvector(v_forward));
3002 VectorClear(PRVM_clientglobalvector(v_right));
3003 VectorClear(PRVM_clientglobalvector(v_up));
3004 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3006 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3008 matrix = skeleton->relativetransforms[bonenum];
3009 // convert to absolute
3010 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3013 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3015 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3016 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3017 VectorNegate(left, PRVM_clientglobalvector(v_right));
3018 VectorCopy(up, PRVM_clientglobalvector(v_up));
3019 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3022 // #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)
3023 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3025 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3026 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3027 vec3_t forward, left, up, origin;
3028 skeleton_t *skeleton;
3030 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3032 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3034 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3035 VectorNegate(PRVM_clientglobalvector(v_right), left);
3036 VectorCopy(PRVM_clientglobalvector(v_up), up);
3037 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3038 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3039 skeleton->relativetransforms[bonenum] = matrix;
3042 // #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)
3043 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3045 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3046 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3047 vec3_t forward, left, up, origin;
3048 skeleton_t *skeleton;
3051 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3053 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3055 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3056 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3057 VectorNegate(PRVM_clientglobalvector(v_right), left);
3058 VectorCopy(PRVM_clientglobalvector(v_up), up);
3059 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3060 temp = skeleton->relativetransforms[bonenum];
3061 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3064 // #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)
3065 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3067 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3068 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3069 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3071 vec3_t forward, left, up, origin;
3072 skeleton_t *skeleton;
3075 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3077 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3078 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3079 VectorNegate(PRVM_clientglobalvector(v_right), left);
3080 VectorCopy(PRVM_clientglobalvector(v_up), up);
3081 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3082 firstbone = max(0, firstbone);
3083 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3084 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3086 temp = skeleton->relativetransforms[bonenum];
3087 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3091 // #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
3092 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3094 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3095 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3096 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3097 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3099 skeleton_t *skeletondst;
3100 skeleton_t *skeletonsrc;
3101 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3103 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3105 firstbone = max(0, firstbone);
3106 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3107 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3108 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3109 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3112 // #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)
3113 static void VM_SV_skel_delete(prvm_prog_t *prog)
3115 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3116 skeleton_t *skeleton;
3117 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3120 prog->skeletons[skeletonindex] = NULL;
3123 // #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
3124 static void VM_SV_frameforname(prvm_prog_t *prog)
3126 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3127 dp_model_t *model = SV_GetModelByIndex(modelindex);
3128 const char *name = PRVM_G_STRING(OFS_PARM1);
3130 PRVM_G_FLOAT(OFS_RETURN) = -1;
3131 if (!model || !model->animscenes)
3133 for (i = 0;i < model->numframes;i++)
3135 if (!strcasecmp(model->animscenes[i].name, name))
3137 PRVM_G_FLOAT(OFS_RETURN) = i;
3143 // #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.
3144 static void VM_SV_frameduration(prvm_prog_t *prog)
3146 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3147 dp_model_t *model = SV_GetModelByIndex(modelindex);
3148 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3149 PRVM_G_FLOAT(OFS_RETURN) = 0;
3150 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3152 if (model->animscenes[framenum].framerate)
3153 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3157 prvm_builtin_t vm_sv_builtins[] = {
3158 NULL, // #0 NULL function (not callable) (QUAKE)
3159 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3160 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3161 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3162 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3163 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3164 VM_break, // #6 void() break (QUAKE)
3165 VM_random, // #7 float() random (QUAKE)
3166 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3167 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3168 VM_error, // #10 void(string e) error (QUAKE)
3169 VM_objerror, // #11 void(string e) objerror (QUAKE)
3170 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3171 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3172 VM_spawn, // #14 entity() spawn (QUAKE)
3173 VM_remove, // #15 void(entity e) remove (QUAKE)
3174 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3175 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3176 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3177 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3178 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3179 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3180 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3181 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3182 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3183 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3184 VM_ftos, // #26 string(float f) ftos (QUAKE)
3185 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3186 VM_coredump, // #28 void() coredump (QUAKE)
3187 VM_traceon, // #29 void() traceon (QUAKE)
3188 VM_traceoff, // #30 void() traceoff (QUAKE)
3189 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3190 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3191 NULL, // #33 (QUAKE)
3192 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3193 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3194 VM_rint, // #36 float(float v) rint (QUAKE)
3195 VM_floor, // #37 float(float v) floor (QUAKE)
3196 VM_ceil, // #38 float(float v) ceil (QUAKE)
3197 NULL, // #39 (QUAKE)
3198 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3199 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3200 NULL, // #42 (QUAKE)
3201 VM_fabs, // #43 float(float f) fabs (QUAKE)
3202 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3203 VM_cvar, // #45 float(string s) cvar (QUAKE)
3204 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3205 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3206 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3207 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3208 NULL, // #50 (QUAKE)
3209 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3210 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3211 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3212 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3213 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3214 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3215 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3216 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3217 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3218 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3219 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3220 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3221 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3222 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3223 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3224 NULL, // #66 (QUAKE)
3225 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3226 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3227 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3228 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3229 NULL, // #71 (QUAKE)
3230 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3231 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3232 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3233 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3234 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3235 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3236 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3237 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3238 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3239 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3240 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3241 NULL, // #83 (QUAKE)
3242 NULL, // #84 (QUAKE)
3243 NULL, // #85 (QUAKE)
3244 NULL, // #86 (QUAKE)
3245 NULL, // #87 (QUAKE)
3246 NULL, // #88 (QUAKE)
3247 NULL, // #89 (QUAKE)
3248 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3249 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3250 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3251 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3252 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3253 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3254 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3255 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3256 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3257 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3258 // FrikaC and Telejano range #100-#199
3269 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3270 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3271 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3272 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3273 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3274 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3275 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3276 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3277 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3278 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3359 // FTEQW range #200-#299
3378 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3381 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3382 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3383 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3384 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3385 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3386 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3387 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3388 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3389 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3390 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3392 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3400 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3423 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.
3424 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
3425 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3426 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3427 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)
3428 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
3429 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)
3430 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)
3431 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)
3432 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)
3433 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)
3434 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
3435 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)
3436 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
3437 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.
3460 // CSQC range #300-#399
3461 NULL, // #300 void() clearscene (EXT_CSQC)
3462 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3463 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3464 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3465 NULL, // #304 void() renderscene (EXT_CSQC)
3466 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3467 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3468 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3469 NULL, // #308 void() R_EndPolygon
3471 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3472 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3476 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3477 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3478 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3479 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3480 NULL, // #319 void(string name) freepic (EXT_CSQC)
3481 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3482 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3483 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3484 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3485 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3486 NULL, // #325 void(void) drawresetcliparea
3491 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3492 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3493 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3494 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3495 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3496 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3497 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3498 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3499 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3500 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3501 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3502 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3503 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3504 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3505 NULL, // #344 vector() getmousepos (EXT_CSQC)
3506 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3507 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3508 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3509 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3510 NULL, // #349 float() isdemo (EXT_CSQC)
3511 VM_isserver, // #350 float() isserver (EXT_CSQC)
3512 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3513 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3514 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3515 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3521 NULL, // #360 float() readbyte (EXT_CSQC)
3522 NULL, // #361 float() readchar (EXT_CSQC)
3523 NULL, // #362 float() readshort (EXT_CSQC)
3524 NULL, // #363 float() readlong (EXT_CSQC)
3525 NULL, // #364 float() readcoord (EXT_CSQC)
3526 NULL, // #365 float() readangle (EXT_CSQC)
3527 NULL, // #366 string() readstring (EXT_CSQC)
3528 NULL, // #367 float() readfloat (EXT_CSQC)
3561 // LordHavoc's range #400-#499
3562 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3563 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3564 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3565 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3566 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3567 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3568 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3569 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3570 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)
3571 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3572 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3573 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3574 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3575 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3576 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3577 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3578 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3579 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3580 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3581 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3582 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3583 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3584 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3585 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3586 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3587 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3588 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3589 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3590 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3591 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3592 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3593 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3594 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3595 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3596 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3597 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3598 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3599 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3600 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3601 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3602 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3603 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3604 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3605 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3606 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3607 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3608 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3609 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3610 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3611 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3612 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3613 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3614 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3615 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3616 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3617 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3618 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3619 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3621 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3622 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3623 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3624 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3625 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3626 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3627 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3628 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3629 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3630 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3631 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3633 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3634 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3635 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3636 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3637 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3638 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3639 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3640 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3641 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3642 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3643 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3644 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3645 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3646 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3647 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3648 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3656 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3657 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3658 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3659 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3660 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3661 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3662 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3663 VM_SV_WritePicture, // #501
3665 VM_whichpack, // #503 string(string) whichpack = #503;
3672 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3673 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3674 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3675 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)
3676 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3677 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3678 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3679 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3680 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3681 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3691 VM_loadfromdata, // #529
3692 VM_loadfromfile, // #530
3693 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3695 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3696 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3702 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3703 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3704 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3767 VM_callfunction, // #605
3768 VM_writetofile, // #606
3769 VM_isfunction, // #607
3775 VM_parseentitydata, // #613
3786 VM_SV_getextresponse, // #624 string getextresponse(void)
3789 VM_sprintf, // #627 string sprintf(string format, ...)
3790 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3791 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3801 VM_digest_hex, // #639
3805 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3807 void SVVM_init_cmd(prvm_prog_t *prog)
3812 void SVVM_reset_cmd(prvm_prog_t *prog)
3814 World_End(&sv.world);
3815 if(PRVM_serverfunction(SV_Shutdown))
3817 func_t s = PRVM_serverfunction(SV_Shutdown);
3818 PRVM_serverglobalfloat(time) = sv.time;
3819 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3820 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");