6 //============================================================================
11 const char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
24 "DP_CSQC_ENTITYWORLDOBJECT "
25 "DP_CSQC_ENTITYMODELLIGHT "
26 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
28 "DP_CSQC_MINFPS_QUALITY "
29 "DP_CSQC_MULTIFRAME_INTERPOLATION "
30 "DP_CSQC_BOXPARTICLES "
31 "DP_CSQC_SPAWNPARTICLE "
32 "DP_CSQC_QUERYRENDERENTITY "
33 "DP_CSQC_ROTATEMOVES "
35 "DP_CSQC_V_CALCREFDEF_WIP1 "
39 "DP_EF_DYNAMICMODELLIGHT "
48 "DP_EF_RESTARTANIM_BIT "
53 "DP_ENT_CUSTOMCOLORMAP "
54 "DP_ENT_EXTERIORMODELTOCLIENT "
57 "DP_ENT_LOWPRECISION "
59 "DP_ENT_TRAILEFFECTNUM "
61 "DP_GFX_EXTERNALTEXTURES "
62 "DP_GFX_EXTERNALTEXTURES_PERMAP "
64 "DP_GFX_MODEL_INTERPOLATION "
65 "DP_GFX_QUAKE3MODELTAGS "
69 "DP_GFX_FONTS_FREETYPE "
71 "DP_FONT_VARIABLEWIDTH "
73 "DP_HALFLIFE_MAP_CVAR "
76 "DP_LIGHTSTYLE_STATICVALUE "
80 "DP_MOVETYPEBOUNCEMISSILE "
81 "DP_MOVETYPEFLYWORLDONLY "
84 "DP_QC_ASINACOSATANATAN2TAN "
90 "DP_QC_CVAR_DEFSTRING "
91 "DP_QC_CVAR_DESCRIPTION "
95 "DP_QC_DIGEST_SHA256 "
100 "DP_QC_EXTRESPONSEPACKET "
102 "DP_QC_FINDCHAINFLAGS "
103 "DP_QC_FINDCHAINFLOAT "
104 "DP_QC_FINDCHAIN_TOFIELD "
110 "DP_QC_GETSURFACETRIANGLE "
111 "DP_QC_GETSURFACEPOINTATTRIBUTE "
113 "DP_QC_GETTAGINFO_BONEPROPERTIES "
115 "DP_QC_GETTIME_CDTRACK "
119 "DP_QC_MULTIPLETEMPSTRINGS "
120 "DP_QC_NUM_FOR_EDICT "
122 "DP_QC_SINCOSSQRTPOW "
125 "DP_QC_STRINGBUFFERS "
126 "DP_QC_STRINGBUFFERS_CVARLIST "
127 "DP_QC_STRINGCOLORFUNCTIONS "
128 "DP_QC_STRING_CASE_FUNCTIONS "
130 "DP_QC_TOKENIZEBYSEPARATOR "
131 "DP_QC_TOKENIZE_CONSOLE "
134 "DP_QC_TRACE_MOVETYPE_HITMODEL "
135 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
136 "DP_QC_UNLIMITEDTEMPSTRINGS "
140 "DP_QC_VECTOANGLES_WITH_ROLL "
141 "DP_QC_VECTORVECTORS "
148 "DP_SKELETONOBJECTS "
149 "DP_SND_DIRECTIONLESSATTNNONE "
151 "DP_SND_SOUND7_WIP1 "
152 "DP_SND_SOUND7_WIP2 "
156 "DP_SND_GETSOUNDTIME "
158 "DP_VIDEO_SUBTITLES "
162 "DP_SV_BOUNCEFACTOR "
163 "DP_SV_CLIENTCAMERA "
164 "DP_SV_CLIENTCOLORS "
167 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
168 "DP_SV_DISCARDABLEDEMO "
169 "DP_SV_DRAWONLYTOCLIENT "
172 "DP_SV_ENTITYCONTENTSTRANSITION "
173 "DP_SV_MODELFLAGS_AS_EFFECTS "
174 "DP_SV_MOVETYPESTEP_LANDEVENT "
176 "DP_SV_NODRAWTOCLIENT "
177 "DP_SV_ONENTITYNOSPAWNFUNCTION "
178 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
180 "DP_SV_PING_PACKETLOSS "
181 "DP_SV_PLAYERPHYSICS "
183 "DP_SV_POINTPARTICLES "
185 "DP_SV_PRECACHEANYTIME "
189 "DP_SV_ROTATINGBMODEL "
193 "DP_SV_SPAWNFUNC_PREFIX "
194 "DP_SV_WRITEPICTURE "
195 "DP_SV_WRITEUNTERMINATEDSTRING "
199 "DP_TE_EXPLOSIONRGB "
201 "DP_TE_PARTICLECUBE "
202 "DP_TE_PARTICLERAIN "
203 "DP_TE_PARTICLESNOW "
205 "DP_TE_QUADEFFECTS1 "
208 "DP_TE_STANDARDEFFECTBUILTINS "
209 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
213 "FTE_CSQC_SKELETONOBJECTS "
216 "KRIMZON_SV_PARSECLIENTCOMMAND "
219 "NEXUIZ_PLAYERMODEL "
221 "PRYDON_CLIENTCURSOR "
222 "TENEBRAE_GFX_DLIGHTS "
225 //"EXT_CSQC " // not ready yet
232 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.
234 setorigin (entity, origin)
237 static void VM_SV_setorigin(prvm_prog_t *prog)
242 VM_SAFEPARMCOUNT(2, VM_setorigin);
244 e = PRVM_G_EDICT(OFS_PARM0);
245 if (e == prog->edicts)
247 VM_Warning(prog, "setorigin: can not modify world entity\n");
250 if (e->priv.server->free)
252 VM_Warning(prog, "setorigin: can not modify free entity\n");
255 org = PRVM_G_VECTOR(OFS_PARM1);
256 VectorCopy (org, PRVM_serveredictvector(e, origin));
257 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
258 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
262 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
263 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qboolean rotate)
267 for (i=0 ; i<3 ; i++)
269 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
271 // set derived values
272 VectorCopy (min, PRVM_serveredictvector(e, mins));
273 VectorCopy (max, PRVM_serveredictvector(e, maxs));
274 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
283 the size box is rotated by the current angle
284 LordHavoc: no it isn't...
286 setsize (entity, minvector, maxvector)
289 static void VM_SV_setsize(prvm_prog_t *prog)
294 VM_SAFEPARMCOUNT(3, VM_setsize);
296 e = PRVM_G_EDICT(OFS_PARM0);
297 if (e == prog->edicts)
299 VM_Warning(prog, "setsize: can not modify world entity\n");
302 if (e->priv.server->free)
304 VM_Warning(prog, "setsize: can not modify free entity\n");
307 min = PRVM_G_VECTOR(OFS_PARM1);
308 max = PRVM_G_VECTOR(OFS_PARM2);
309 SetMinMaxSize(prog, e, min, max, false);
317 setmodel(entity, model)
320 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
321 static void VM_SV_setmodel(prvm_prog_t *prog)
327 VM_SAFEPARMCOUNT(2, VM_setmodel);
329 e = PRVM_G_EDICT(OFS_PARM0);
330 if (e == prog->edicts)
332 VM_Warning(prog, "setmodel: can not modify world entity\n");
335 if (e->priv.server->free)
337 VM_Warning(prog, "setmodel: can not modify free entity\n");
340 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
341 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
342 PRVM_serveredictfloat(e, modelindex) = i;
344 mod = SV_GetModelByIndex(i);
348 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
349 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
351 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
354 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
361 single print to a specific client
363 sprint(clientent, value)
366 static void VM_SV_sprint(prvm_prog_t *prog)
370 char string[VM_STRINGTEMP_LENGTH];
372 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
374 VM_VarString(prog, 1, string, sizeof(string));
376 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
377 // LordHavoc: div0 requested that sprintto world operate like print
384 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
386 VM_Warning(prog, "tried to centerprint to a non-client\n");
390 client = svs.clients + entnum-1;
391 if (!client->netconnection)
394 MSG_WriteChar(&client->netconnection->message,svc_print);
395 MSG_WriteString(&client->netconnection->message, string);
403 single print to a specific client
405 centerprint(clientent, value)
408 static void VM_SV_centerprint(prvm_prog_t *prog)
412 char string[VM_STRINGTEMP_LENGTH];
414 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
416 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
418 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
420 VM_Warning(prog, "tried to centerprint to a non-client\n");
424 client = svs.clients + entnum-1;
425 if (!client->netconnection)
428 VM_VarString(prog, 1, string, sizeof(string));
429 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
430 MSG_WriteString(&client->netconnection->message, string);
437 particle(origin, color, count)
440 static void VM_SV_particle(prvm_prog_t *prog)
446 VM_SAFEPARMCOUNT(4, VM_SV_particle);
448 org = PRVM_G_VECTOR(OFS_PARM0);
449 dir = PRVM_G_VECTOR(OFS_PARM1);
450 color = PRVM_G_FLOAT(OFS_PARM2);
451 count = PRVM_G_FLOAT(OFS_PARM3);
452 SV_StartParticle (org, dir, (int)color, (int)count);
462 static void VM_SV_ambientsound(prvm_prog_t *prog)
466 float vol, attenuation;
469 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
471 pos = PRVM_G_VECTOR (OFS_PARM0);
472 samp = PRVM_G_STRING(OFS_PARM1);
473 vol = PRVM_G_FLOAT(OFS_PARM2);
474 attenuation = PRVM_G_FLOAT(OFS_PARM3);
476 // check to see if samp was properly precached
477 soundnum = SV_SoundIndex(samp, 1);
485 // add an svc_spawnambient command to the level signon packet
488 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
490 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
492 MSG_WriteVector(&sv.signon, pos, sv.protocol);
494 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
495 MSG_WriteShort (&sv.signon, soundnum);
497 MSG_WriteByte (&sv.signon, soundnum);
499 MSG_WriteByte (&sv.signon, (int)(vol*255));
500 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
508 Each entity can have eight independant sound sources, like voice,
511 Channel 0 is an auto-allocate channel, the others override anything
512 already running on that entity/channel pair.
514 An attenuation of 0 will play full volume everywhere in the level.
515 Larger attenuations will drop off.
519 static void VM_SV_sound(prvm_prog_t *prog)
523 prvm_edict_t *entity;
529 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
531 entity = PRVM_G_EDICT(OFS_PARM0);
532 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
533 sample = PRVM_G_STRING(OFS_PARM2);
534 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
537 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
541 attenuation = PRVM_G_FLOAT(OFS_PARM4);
545 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
550 if(channel >= 8 && channel <= 15) // weird QW feature
552 flags |= CHANFLAG_RELIABLE;
557 flags = PRVM_G_FLOAT(OFS_PARM6);
559 if (volume < 0 || volume > 255)
561 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
565 if (attenuation < 0 || attenuation > 4)
567 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
571 channel = CHAN_USER2ENGINE(channel);
573 if (!IS_CHAN(channel))
575 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
579 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE, pitchchange);
586 Follows the same logic as VM_SV_sound, except instead of
587 an entity, an origin for the sound is provided, and channel
588 is omitted (since no entity is being tracked).
592 static void VM_SV_pointsound(prvm_prog_t *prog)
600 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
602 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
603 sample = PRVM_G_STRING(OFS_PARM1);
604 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
605 attenuation = PRVM_G_FLOAT(OFS_PARM3);
606 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
608 if (volume < 0 || volume > 255)
610 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
614 if (attenuation < 0 || attenuation > 4)
616 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
620 SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
627 Used for use tracing and shot targeting
628 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
629 if the tryents flag is set.
631 traceline (vector1, vector2, movetype, ignore)
634 static void VM_SV_traceline(prvm_prog_t *prog)
641 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
643 prog->xfunction->builtinsprofile += 30;
645 v1 = PRVM_G_VECTOR(OFS_PARM0);
646 v2 = PRVM_G_VECTOR(OFS_PARM1);
647 move = (int)PRVM_G_FLOAT(OFS_PARM2);
648 ent = PRVM_G_EDICT(OFS_PARM3);
650 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]))
651 prog->error_cmd("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
653 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
655 VM_SetTraceGlobals(prog, &trace);
663 Used for use tracing and shot targeting
664 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
665 if the tryents flag is set.
667 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
670 // LordHavoc: added this for my own use, VERY useful, similar to traceline
671 static void VM_SV_tracebox(prvm_prog_t *prog)
673 float *v1, *v2, *m1, *m2;
678 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
680 prog->xfunction->builtinsprofile += 30;
682 v1 = PRVM_G_VECTOR(OFS_PARM0);
683 m1 = PRVM_G_VECTOR(OFS_PARM1);
684 m2 = PRVM_G_VECTOR(OFS_PARM2);
685 v2 = PRVM_G_VECTOR(OFS_PARM3);
686 move = (int)PRVM_G_FLOAT(OFS_PARM4);
687 ent = PRVM_G_EDICT(OFS_PARM5);
689 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]))
690 prog->error_cmd("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
692 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
694 VM_SetTraceGlobals(prog, &trace);
697 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
702 vec3_t original_origin;
703 vec3_t original_velocity;
704 vec3_t original_angles;
705 vec3_t original_avelocity;
708 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
709 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
710 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
711 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
713 gravity = PRVM_serveredictfloat(tossent, gravity);
716 gravity *= sv_gravity.value * 0.025;
718 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
720 SV_CheckVelocity (tossent);
721 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
722 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
723 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
724 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
725 trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
726 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
727 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
729 if (trace.fraction < 1)
733 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
734 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
735 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
736 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
741 static void VM_SV_tracetoss(prvm_prog_t *prog)
745 prvm_edict_t *ignore;
747 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
749 prog->xfunction->builtinsprofile += 600;
751 ent = PRVM_G_EDICT(OFS_PARM0);
752 if (ent == prog->edicts)
754 VM_Warning(prog, "tracetoss: can not use world entity\n");
757 ignore = PRVM_G_EDICT(OFS_PARM1);
759 trace = SV_Trace_Toss(prog, ent, ignore);
761 VM_SetTraceGlobals(prog, &trace);
764 //============================================================================
766 static int checkpvsbytes;
767 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
769 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
775 // cycle to the next one
777 check = bound(1, check, svs.maxclients);
778 if (check == svs.maxclients)
786 prog->xfunction->builtinsprofile++;
788 if (i == svs.maxclients+1)
790 // look up the client's edict
791 ent = PRVM_EDICT_NUM(i);
792 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
793 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
795 // found a valid client (possibly the same one again)
799 // get the PVS for the entity
800 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
802 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
803 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
812 Returns a client (or object that has a client enemy) that would be a
815 If there is more than one valid option, they are cycled each frame
817 If (self.origin + self.viewofs) is not in the PVS of the current target,
818 it is not returned at all.
823 int c_invis, c_notvis;
824 static void VM_SV_checkclient(prvm_prog_t *prog)
826 prvm_edict_t *ent, *self;
829 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
831 // find a new check if on a new frame
832 if (sv.time - sv.lastchecktime >= 0.1)
834 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
835 sv.lastchecktime = sv.time;
838 // return check if it might be visible
839 ent = PRVM_EDICT_NUM(sv.lastcheck);
840 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
842 VM_RETURN_EDICT(prog->edicts);
846 // if current entity can't possibly see the check entity, return 0
847 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
848 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
849 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
852 VM_RETURN_EDICT(prog->edicts);
856 // might be able to see it
858 VM_RETURN_EDICT(ent);
861 //============================================================================
867 Checks if an entity is in a point's PVS.
868 Should be fast but can be inexact.
870 float checkpvs(vector viewpos, entity viewee) = #240;
873 static void VM_SV_checkpvs(prvm_prog_t *prog)
876 prvm_edict_t *viewee;
881 unsigned char fatpvs[MAX_MAP_LEAFS/8];
884 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
885 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
886 viewee = PRVM_G_EDICT(OFS_PARM1);
888 if(viewee->priv.server->free)
890 VM_Warning(prog, "checkpvs: can not check free entity\n");
891 PRVM_G_FLOAT(OFS_RETURN) = 4;
896 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
898 // no PVS support on this worldmodel... darn
899 PRVM_G_FLOAT(OFS_RETURN) = 3;
902 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
905 // viewpos isn't in any PVS... darn
906 PRVM_G_FLOAT(OFS_RETURN) = 2;
909 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
911 // using fat PVS like FTEQW does (slow)
912 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
914 // no PVS support on this worldmodel... darn
915 PRVM_G_FLOAT(OFS_RETURN) = 3;
918 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
921 // viewpos isn't in any PVS... darn
922 PRVM_G_FLOAT(OFS_RETURN) = 2;
925 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
934 Sends text over to the client's execution buffer
936 stuffcmd (clientent, value, ...)
939 static void VM_SV_stuffcmd(prvm_prog_t *prog)
943 char string[VM_STRINGTEMP_LENGTH];
945 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
947 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
948 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
950 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
954 VM_VarString(prog, 1, string, sizeof(string));
957 host_client = svs.clients + entnum-1;
958 Host_ClientCommands ("%s", string);
966 Returns a chain of entities that have origins within a spherical area
968 findradius (origin, radius)
971 static void VM_SV_findradius(prvm_prog_t *prog)
973 prvm_edict_t *ent, *chain;
974 vec_t radius, radius2;
975 vec3_t org, eorg, mins, maxs;
978 static prvm_edict_t *touchedicts[MAX_EDICTS];
981 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
984 chainfield = PRVM_G_INT(OFS_PARM2);
986 chainfield = prog->fieldoffsets.chain;
988 prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
990 chain = (prvm_edict_t *)prog->edicts;
992 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
993 radius = PRVM_G_FLOAT(OFS_PARM1);
994 radius2 = radius * radius;
996 mins[0] = org[0] - (radius + 1);
997 mins[1] = org[1] - (radius + 1);
998 mins[2] = org[2] - (radius + 1);
999 maxs[0] = org[0] + (radius + 1);
1000 maxs[1] = org[1] + (radius + 1);
1001 maxs[2] = org[2] + (radius + 1);
1002 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1003 if (numtouchedicts > MAX_EDICTS)
1005 // this never happens
1006 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1007 numtouchedicts = MAX_EDICTS;
1009 for (i = 0;i < numtouchedicts;i++)
1011 ent = touchedicts[i];
1012 prog->xfunction->builtinsprofile++;
1013 // Quake did not return non-solid entities but darkplaces does
1014 // (note: this is the reason you can't blow up fallen zombies)
1015 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1017 // LordHavoc: compare against bounding box rather than center so it
1018 // doesn't miss large objects, and use DotProduct instead of Length
1019 // for a major speedup
1020 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1021 if (sv_gameplayfix_findradiusdistancetobox.integer)
1023 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1024 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1025 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1028 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1029 if (DotProduct(eorg, eorg) < radius2)
1031 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1036 VM_RETURN_EDICT(chain);
1039 static void VM_SV_precache_sound(prvm_prog_t *prog)
1041 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1042 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1045 static void VM_SV_precache_model(prvm_prog_t *prog)
1047 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1048 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1049 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1056 float(float yaw, float dist[, settrace]) walkmove
1059 static void VM_SV_walkmove(prvm_prog_t *prog)
1068 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1070 // assume failure if it returns early
1071 PRVM_G_FLOAT(OFS_RETURN) = 0;
1073 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1074 if (ent == prog->edicts)
1076 VM_Warning(prog, "walkmove: can not modify world entity\n");
1079 if (ent->priv.server->free)
1081 VM_Warning(prog, "walkmove: can not modify free entity\n");
1084 yaw = PRVM_G_FLOAT(OFS_PARM0);
1085 dist = PRVM_G_FLOAT(OFS_PARM1);
1086 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1088 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1091 yaw = yaw*M_PI*2 / 360;
1093 move[0] = cos(yaw)*dist;
1094 move[1] = sin(yaw)*dist;
1097 // save program state, because SV_movestep may call other progs
1098 oldf = prog->xfunction;
1099 oldself = PRVM_serverglobaledict(self);
1101 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1104 // restore program state
1105 prog->xfunction = oldf;
1106 PRVM_serverglobaledict(self) = oldself;
1117 static void VM_SV_droptofloor(prvm_prog_t *prog)
1123 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1125 // assume failure if it returns early
1126 PRVM_G_FLOAT(OFS_RETURN) = 0;
1128 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1129 if (ent == prog->edicts)
1131 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1134 if (ent->priv.server->free)
1136 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1140 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1143 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1144 if (sv_gameplayfix_unstickentities.integer)
1145 SV_UnstickEntity(ent);
1147 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1148 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1151 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]);
1152 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1153 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1154 VectorSubtract(trace.endpos, offset, trace.endpos);
1155 if (trace.startsolid)
1157 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]);
1158 if (sv_gameplayfix_unstickentities.integer)
1159 SV_UnstickEntity(ent);
1161 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1162 PRVM_serveredictedict(ent, groundentity) = 0;
1163 PRVM_G_FLOAT(OFS_RETURN) = 1;
1165 else if (trace.fraction < 1)
1167 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]);
1168 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1169 if (sv_gameplayfix_unstickentities.integer)
1170 SV_UnstickEntity(ent);
1172 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1173 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1174 PRVM_G_FLOAT(OFS_RETURN) = 1;
1175 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1176 ent->priv.server->suspendedinairflag = true;
1181 if (trace.fraction != 1)
1183 if (trace.fraction < 1)
1184 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1186 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1187 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1188 PRVM_G_FLOAT(OFS_RETURN) = 1;
1189 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1190 ent->priv.server->suspendedinairflag = true;
1199 void(float style, string value) lightstyle
1202 static void VM_SV_lightstyle(prvm_prog_t *prog)
1209 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1211 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1212 val = PRVM_G_STRING(OFS_PARM1);
1214 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1215 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1218 // change the string in sv
1219 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1221 // send message to all clients on this server
1222 if (sv.state != ss_active)
1225 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1227 if (client->active && client->netconnection)
1229 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1230 MSG_WriteChar (&client->netconnection->message,style);
1231 MSG_WriteString (&client->netconnection->message, val);
1241 static void VM_SV_checkbottom(prvm_prog_t *prog)
1243 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1244 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1252 static void VM_SV_pointcontents(prvm_prog_t *prog)
1254 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1255 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1262 Pick a vector for the player to shoot along
1263 vector aim(entity, missilespeed)
1266 static void VM_SV_aim(prvm_prog_t *prog)
1268 prvm_edict_t *ent, *check, *bestent;
1269 vec3_t start, dir, end, bestdir;
1272 float dist, bestdist;
1275 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1277 // assume failure if it returns early
1278 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1279 // if sv_aim is so high it can't possibly accept anything, skip out early
1280 if (sv_aim.value >= 1)
1283 ent = PRVM_G_EDICT(OFS_PARM0);
1284 if (ent == prog->edicts)
1286 VM_Warning(prog, "aim: can not use world entity\n");
1289 if (ent->priv.server->free)
1291 VM_Warning(prog, "aim: can not use free entity\n");
1294 //speed = PRVM_G_FLOAT(OFS_PARM1);
1296 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1299 // try sending a trace straight
1300 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1301 VectorMA (start, 2048, dir, end);
1302 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1303 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1304 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1306 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1311 // try all possible entities
1312 VectorCopy (dir, bestdir);
1313 bestdist = sv_aim.value;
1316 check = PRVM_NEXT_EDICT(prog->edicts);
1317 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1319 prog->xfunction->builtinsprofile++;
1320 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1324 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1325 continue; // don't aim at teammate
1326 for (j=0 ; j<3 ; j++)
1327 end[j] = PRVM_serveredictvector(check, origin)[j]
1328 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1329 VectorSubtract (end, start, dir);
1330 VectorNormalize (dir);
1331 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1332 if (dist < bestdist)
1333 continue; // to far to turn
1334 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1335 if (tr.ent == check)
1336 { // can shoot at this one
1344 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1345 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1346 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1348 VectorNormalize (end);
1349 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1353 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1358 ===============================================================================
1362 ===============================================================================
1365 #define MSG_BROADCAST 0 // unreliable to all
1366 #define MSG_ONE 1 // reliable to one (msg_entity)
1367 #define MSG_ALL 2 // reliable to all
1368 #define MSG_INIT 3 // write to the init string
1369 #define MSG_ENTITY 5
1371 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1377 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1381 return &sv.datagram;
1384 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1385 entnum = PRVM_NUM_FOR_EDICT(ent);
1386 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1388 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1389 return &sv.reliable_datagram;
1392 return &svs.clients[entnum-1].netconnection->message;
1395 VM_Warning(prog, "WriteDest: bad destination\n");
1397 return &sv.reliable_datagram;
1403 return sv.writeentitiestoclient_msg;
1409 static void VM_SV_WriteByte(prvm_prog_t *prog)
1411 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1412 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1415 static void VM_SV_WriteChar(prvm_prog_t *prog)
1417 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1418 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1421 static void VM_SV_WriteShort(prvm_prog_t *prog)
1423 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1424 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1427 static void VM_SV_WriteLong(prvm_prog_t *prog)
1429 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1430 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1433 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1435 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1436 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1439 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1441 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1442 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1445 static void VM_SV_WriteString(prvm_prog_t *prog)
1447 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1448 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1451 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1453 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1454 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1458 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1460 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1461 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1464 // writes a picture as at most size bytes of data
1466 // IMGNAME \0 SIZE(short) IMGDATA
1467 // if failed to read/compress:
1469 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1470 static void VM_SV_WritePicture(prvm_prog_t *prog)
1472 const char *imgname;
1476 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1478 imgname = PRVM_G_STRING(OFS_PARM1);
1479 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1483 MSG_WriteString(WriteDest(prog), imgname);
1484 if(Image_Compress(imgname, size, &buf, &size))
1487 MSG_WriteShort(WriteDest(prog), size);
1488 SZ_Write(WriteDest(prog), (unsigned char *) buf, size);
1493 MSG_WriteShort(WriteDest(prog), 0);
1497 //////////////////////////////////////////////////////////
1499 static void VM_SV_makestatic(prvm_prog_t *prog)
1504 // allow 0 parameters due to an id1 qc bug in which this function is used
1505 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1506 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1508 if (prog->argc >= 1)
1509 ent = PRVM_G_EDICT(OFS_PARM0);
1511 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1512 if (ent == prog->edicts)
1514 VM_Warning(prog, "makestatic: can not modify world entity\n");
1517 if (ent->priv.server->free)
1519 VM_Warning(prog, "makestatic: can not modify free entity\n");
1524 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1529 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1530 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1531 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1533 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1535 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1536 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1537 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1541 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1542 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1543 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1546 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1547 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1548 for (i=0 ; i<3 ; i++)
1550 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1551 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1554 // throw the entity away now
1555 PRVM_ED_Free(prog, ent);
1558 //=============================================================================
1565 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1571 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1573 ent = PRVM_G_EDICT(OFS_PARM0);
1574 i = PRVM_NUM_FOR_EDICT(ent);
1575 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1577 Con_Print("tried to setspawnparms on a non-client\n");
1581 // copy spawn parms out of the client_t
1582 client = svs.clients + i-1;
1583 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1584 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1591 Returns a color vector indicating the lighting at the requested point.
1593 (Internal Operation note: actually measures the light beneath the point, just like
1594 the model lighting on the client)
1599 static void VM_SV_getlight(prvm_prog_t *prog)
1601 vec3_t ambientcolor, diffusecolor, diffusenormal;
1603 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1604 p = PRVM_G_VECTOR(OFS_PARM0);
1605 VectorClear(ambientcolor);
1606 VectorClear(diffusecolor);
1607 VectorClear(diffusenormal);
1608 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1609 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1610 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1615 unsigned char type; // 1/2/8 or other value if isn't used
1619 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1620 static int vm_customstats_last;
1622 void VM_CustomStats_Clear (void)
1626 Z_Free(vm_customstats);
1627 vm_customstats = NULL;
1628 vm_customstats_last = -1;
1632 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1634 prvm_prog_t *prog = SVVM_prog;
1641 for(i=0; i<vm_customstats_last+1 ;i++)
1643 if(!vm_customstats[i].type)
1645 switch(vm_customstats[i].type)
1647 //string as 16 bytes
1650 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1651 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1652 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1653 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1654 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1656 //float field sent as-is
1658 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1660 //integer value of float field
1662 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1670 // void(float index, float type, .void field) SV_AddStat = #232;
1671 // Set up an auto-sent player stat.
1672 // Client's get thier own fields sent to them. Index may not be less than 32.
1673 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1674 // 1: string (4 stats carrying a total of 16 charactures)
1675 // 2: float (one stat, float converted to an integer for transportation)
1676 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1677 static void VM_SV_AddStat(prvm_prog_t *prog)
1682 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1686 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1689 VM_Warning(prog, "PF_SV_AddStat: not enough memory\n");
1693 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1694 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1695 off = PRVM_G_INT (OFS_PARM2);
1700 VM_Warning(prog, "PF_SV_AddStat: index may not be less than 32\n");
1703 if(i >= (MAX_CL_STATS-32))
1705 VM_Warning(prog, "PF_SV_AddStat: index >= MAX_CL_STATS\n");
1708 if(i > (MAX_CL_STATS-32-4) && type == 1)
1710 VM_Warning(prog, "PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1713 vm_customstats[i].type = type;
1714 vm_customstats[i].fieldoffset = off;
1715 if(vm_customstats_last < i)
1716 vm_customstats_last = i;
1723 copies data from one entity to another
1725 copyentity(src, dst)
1728 static void VM_SV_copyentity(prvm_prog_t *prog)
1730 prvm_edict_t *in, *out;
1731 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1732 in = PRVM_G_EDICT(OFS_PARM0);
1733 if (in == prog->edicts)
1735 VM_Warning(prog, "copyentity: can not read world entity\n");
1738 if (in->priv.server->free)
1740 VM_Warning(prog, "copyentity: can not read free entity\n");
1743 out = PRVM_G_EDICT(OFS_PARM1);
1744 if (out == prog->edicts)
1746 VM_Warning(prog, "copyentity: can not modify world entity\n");
1749 if (out->priv.server->free)
1751 VM_Warning(prog, "copyentity: can not modify free entity\n");
1754 memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
1763 sets the color of a client and broadcasts the update to all connected clients
1765 setcolor(clientent, value)
1768 static void VM_SV_setcolor(prvm_prog_t *prog)
1773 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1774 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1775 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1777 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1779 Con_Print("tried to setcolor a non-client\n");
1783 client = svs.clients + entnum-1;
1786 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1787 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1790 if (client->old_colors != client->colors)
1792 client->old_colors = client->colors;
1793 // send notification to all clients
1794 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1795 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1796 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1804 effect(origin, modelname, startframe, framecount, framerate)
1807 static void VM_SV_effect(prvm_prog_t *prog)
1811 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1812 s = PRVM_G_STRING(OFS_PARM1);
1815 VM_Warning(prog, "effect: no model specified\n");
1819 i = SV_ModelIndex(s, 1);
1822 VM_Warning(prog, "effect: model not precached\n");
1826 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1828 VM_Warning(prog, "effect: framecount < 1\n");
1832 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1834 VM_Warning(prog, "effect: framerate < 1\n");
1838 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));
1841 static void VM_SV_te_blood(prvm_prog_t *prog)
1843 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1844 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1846 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1847 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1849 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1850 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1851 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1853 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1854 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1855 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1857 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1858 SV_FlushBroadcastMessages();
1861 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1863 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1864 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1866 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1867 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1869 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1870 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1873 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1874 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1875 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1877 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1879 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1880 SV_FlushBroadcastMessages();
1883 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1885 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1886 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1887 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1889 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1890 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1891 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1893 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1894 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1895 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1896 SV_FlushBroadcastMessages();
1899 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1901 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1902 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1904 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1905 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1911 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1912 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1913 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1915 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1916 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1917 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1919 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1921 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1922 // gravity true/false
1923 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1925 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1926 SV_FlushBroadcastMessages();
1929 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1931 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1932 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1934 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1935 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1941 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1942 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1943 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1945 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1949 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1951 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1952 SV_FlushBroadcastMessages();
1955 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1957 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1958 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1960 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1961 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1964 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1965 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1972 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1973 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1975 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1977 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1978 SV_FlushBroadcastMessages();
1981 static void VM_SV_te_spark(prvm_prog_t *prog)
1983 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1984 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1986 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1987 MSG_WriteByte(&sv.datagram, TE_SPARK);
1989 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1990 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1991 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1993 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1994 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1995 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1997 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1998 SV_FlushBroadcastMessages();
2001 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2003 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2004 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2005 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2007 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2008 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2009 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2010 SV_FlushBroadcastMessages();
2013 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2015 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2016 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2017 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2019 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2020 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2021 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2022 SV_FlushBroadcastMessages();
2025 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2027 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2028 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2029 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2031 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2032 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2033 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2034 SV_FlushBroadcastMessages();
2037 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2039 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2040 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2041 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2043 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2044 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2045 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2046 SV_FlushBroadcastMessages();
2049 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2051 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2052 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2053 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2055 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2056 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2058 SV_FlushBroadcastMessages();
2061 static void VM_SV_te_customflash(prvm_prog_t *prog)
2063 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2064 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2066 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2067 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2069 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2070 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2071 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2073 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2075 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2077 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2078 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2079 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2080 SV_FlushBroadcastMessages();
2083 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2085 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2086 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2087 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2089 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2090 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2091 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2092 SV_FlushBroadcastMessages();
2095 static void VM_SV_te_spike(prvm_prog_t *prog)
2097 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2098 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2099 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2101 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2102 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2103 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2104 SV_FlushBroadcastMessages();
2107 static void VM_SV_te_superspike(prvm_prog_t *prog)
2109 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2110 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2111 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2113 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2114 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2115 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2116 SV_FlushBroadcastMessages();
2119 static void VM_SV_te_explosion(prvm_prog_t *prog)
2121 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2122 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2123 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2125 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2126 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2127 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2128 SV_FlushBroadcastMessages();
2131 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2133 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2134 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2135 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2137 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2138 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2139 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2140 SV_FlushBroadcastMessages();
2143 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2145 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2146 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2147 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2149 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2150 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2151 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2152 SV_FlushBroadcastMessages();
2155 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2157 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2158 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2159 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2161 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2162 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2163 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2164 SV_FlushBroadcastMessages();
2167 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2169 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2170 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2171 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2173 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2174 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2175 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2176 SV_FlushBroadcastMessages();
2179 static void VM_SV_te_teleport(prvm_prog_t *prog)
2181 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2182 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2183 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2185 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2186 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2187 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2188 SV_FlushBroadcastMessages();
2191 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2193 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2194 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2195 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2197 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2198 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2199 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2201 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2202 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2203 SV_FlushBroadcastMessages();
2206 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2208 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2209 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2210 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2212 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2214 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2215 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2216 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2218 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2219 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2220 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2221 SV_FlushBroadcastMessages();
2224 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2226 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2227 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2228 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2230 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2232 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2234 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2236 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2237 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2238 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2239 SV_FlushBroadcastMessages();
2242 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2244 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2245 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2246 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2248 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2250 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2251 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2252 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2254 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2255 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2256 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2257 SV_FlushBroadcastMessages();
2260 static void VM_SV_te_beam(prvm_prog_t *prog)
2262 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2263 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2264 MSG_WriteByte(&sv.datagram, TE_BEAM);
2266 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2268 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2269 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2270 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2272 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2273 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2274 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2275 SV_FlushBroadcastMessages();
2278 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2280 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2281 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2282 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2283 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2284 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2285 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2286 SV_FlushBroadcastMessages();
2289 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2291 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2292 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2293 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2295 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2296 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2297 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2299 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2300 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2301 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2303 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2304 SV_FlushBroadcastMessages();
2307 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2308 //this function originally written by KrimZon, made shorter by LordHavoc
2309 static void VM_SV_clientcommand(prvm_prog_t *prog)
2311 client_t *temp_client;
2313 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2315 //find client for this entity
2316 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2317 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2319 Con_Print("PF_clientcommand: entity is not a client\n");
2323 temp_client = host_client;
2324 host_client = svs.clients + i;
2325 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
2326 host_client = temp_client;
2329 //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)
2330 static void VM_SV_setattachment(prvm_prog_t *prog)
2332 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2333 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2334 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2337 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2339 if (e == prog->edicts)
2341 VM_Warning(prog, "setattachment: can not modify world entity\n");
2344 if (e->priv.server->free)
2346 VM_Warning(prog, "setattachment: can not modify free entity\n");
2350 if (tagentity == NULL)
2351 tagentity = prog->edicts;
2355 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2357 model = SV_GetModelFromEdict(tagentity);
2360 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2362 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);
2365 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));
2368 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2369 PRVM_serveredictfloat(e, tag_index) = tagindex;
2372 /////////////////////////////////////////
2373 // DP_MD3_TAGINFO extension coded by VorteX
2375 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2379 i = (int)PRVM_serveredictfloat(e, modelindex);
2380 if (i < 1 || i >= MAX_MODELS)
2383 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2386 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2393 Matrix4x4_CreateIdentity(tag_localmatrix);
2395 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2397 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2408 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2411 float pitchsign = 1;
2413 scale = PRVM_serveredictfloat(ent, scale);
2418 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);
2421 pitchsign = SV_GetPitchSign(prog, ent);
2422 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);
2426 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2429 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2431 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2432 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2433 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2434 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2436 *out = identitymatrix;
2440 // Warnings/errors code:
2441 // 0 - normal (everything all-right)
2444 // 3 - null or non-precached model
2445 // 4 - no tags with requested index
2446 // 5 - runaway loop at attachment chain
2447 extern cvar_t cl_bob;
2448 extern cvar_t cl_bobcycle;
2449 extern cvar_t cl_bobup;
2450 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2453 int modelindex, attachloop;
2454 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2457 *out = identitymatrix; // warnings and errors return identical matrix
2459 if (ent == prog->edicts)
2461 if (ent->priv.server->free)
2464 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2465 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2468 model = SV_GetModelByIndex(modelindex);
2470 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2471 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2472 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2474 tagmatrix = identitymatrix;
2475 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2479 if (attachloop >= 256) // prevent runaway looping
2481 // apply transformation by child's tagindex on parent entity and then
2482 // by parent entity itself
2483 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2484 if (ret && attachloop == 0)
2486 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2487 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2488 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2489 // next iteration we process the parent entity
2490 if (PRVM_serveredictedict(ent, tag_entity))
2492 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2493 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2500 // RENDER_VIEWMODEL magic
2501 if (PRVM_serveredictedict(ent, viewmodelforclient))
2503 Matrix4x4_Copy(&tagmatrix, out);
2504 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2506 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2507 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2510 // Cl_bob, ported from rendering code
2511 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2514 // LordHavoc: this code is *weird*, but not replacable (I think it
2515 // should be done in QC on the server, but oh well, quake is quake)
2516 // LordHavoc: figured out bobup: the time at which the sin is at 180
2517 // degrees (which allows lengthening or squishing the peak or valley)
2518 cycle = sv.time/cl_bobcycle.value;
2519 cycle -= (int)cycle;
2520 if (cycle < cl_bobup.value)
2521 cycle = sin(M_PI * cycle / cl_bobup.value);
2523 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2524 // bob is proportional to velocity in the xy plane
2525 // (don't count Z, or jumping messes it up)
2526 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;
2527 bob = bob*0.3 + bob*0.7*cycle;
2528 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2535 //float(entity ent, string tagname) gettagindex;
2537 static void VM_SV_gettagindex(prvm_prog_t *prog)
2540 const char *tag_name;
2543 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2545 ent = PRVM_G_EDICT(OFS_PARM0);
2546 tag_name = PRVM_G_STRING(OFS_PARM1);
2548 if (ent == prog->edicts)
2550 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2553 if (ent->priv.server->free)
2555 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2560 if (!SV_GetModelFromEdict(ent))
2561 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2564 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2566 if(developer_extra.integer)
2567 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2569 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2572 //vector(entity ent, float tagindex) gettaginfo;
2573 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2577 matrix4x4_t tag_matrix;
2578 matrix4x4_t tag_localmatrix;
2580 const char *tagname;
2582 vec3_t fo, le, up, trans;
2583 const dp_model_t *model;
2585 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2587 e = PRVM_G_EDICT(OFS_PARM0);
2588 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2590 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2591 Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
2592 VectorScale(le, -1, PRVM_serverglobalvector(v_right));
2593 model = SV_GetModelFromEdict(e);
2594 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2595 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
2596 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2597 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2598 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2600 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2601 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2602 VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
2603 VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
2604 VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
2605 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2610 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2613 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2616 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2619 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2622 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2627 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2628 static void VM_SV_dropclient(prvm_prog_t *prog)
2631 client_t *oldhostclient;
2632 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2633 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2634 if (clientnum < 0 || clientnum >= svs.maxclients)
2636 VM_Warning(prog, "dropclient: not a client\n");
2639 if (!svs.clients[clientnum].active)
2641 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2644 oldhostclient = host_client;
2645 host_client = svs.clients + clientnum;
2646 SV_DropClient(false);
2647 host_client = oldhostclient;
2650 //entity() spawnclient (DP_SV_BOTCLIENT)
2651 static void VM_SV_spawnclient(prvm_prog_t *prog)
2655 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2656 prog->xfunction->builtinsprofile += 2;
2658 for (i = 0;i < svs.maxclients;i++)
2660 if (!svs.clients[i].active)
2662 prog->xfunction->builtinsprofile += 100;
2663 SV_ConnectClient (i, NULL);
2664 // this has to be set or else ClientDisconnect won't be called
2665 // we assume the qc will call ClientConnect...
2666 svs.clients[i].clientconnectcalled = true;
2667 ed = PRVM_EDICT_NUM(i + 1);
2671 VM_RETURN_EDICT(ed);
2674 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2675 static void VM_SV_clienttype(prvm_prog_t *prog)
2678 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2679 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2680 if (clientnum < 0 || clientnum >= svs.maxclients)
2681 PRVM_G_FLOAT(OFS_RETURN) = 3;
2682 else if (!svs.clients[clientnum].active)
2683 PRVM_G_FLOAT(OFS_RETURN) = 0;
2684 else if (svs.clients[clientnum].netconnection)
2685 PRVM_G_FLOAT(OFS_RETURN) = 1;
2687 PRVM_G_FLOAT(OFS_RETURN) = 2;
2694 string(string key) serverkey
2697 static void VM_SV_serverkey(prvm_prog_t *prog)
2699 char string[VM_STRINGTEMP_LENGTH];
2700 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2701 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2702 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2705 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2706 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2711 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2713 e = PRVM_G_EDICT(OFS_PARM0);
2714 if (e == prog->edicts)
2716 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2719 if (e->priv.server->free)
2721 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2724 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2725 if (i <= 0 || i >= MAX_MODELS)
2727 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2730 if (!sv.model_precache[i][0])
2732 VM_Warning(prog, "setmodelindex: model not precached\n");
2736 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2737 PRVM_serveredictfloat(e, modelindex) = i;
2739 mod = SV_GetModelByIndex(i);
2743 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2744 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2746 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2749 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2752 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2753 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2756 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2758 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2760 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2761 if (i <= 0 || i >= MAX_MODELS)
2763 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2766 if (!sv.model_precache[i][0])
2768 VM_Warning(prog, "modelnameforindex: model not precached\n");
2772 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2775 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2776 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2779 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2780 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2783 PRVM_G_FLOAT(OFS_RETURN) = i;
2786 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2787 static void VM_SV_trailparticles(prvm_prog_t *prog)
2789 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2791 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2794 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2795 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2796 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2797 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2798 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2799 SV_FlushBroadcastMessages();
2802 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2803 static void VM_SV_pointparticles(prvm_prog_t *prog)
2805 int effectnum, count;
2807 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2809 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2812 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2813 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2814 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2815 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2816 if (count == 1 && !VectorLength2(vel))
2819 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2820 MSG_WriteShort(&sv.datagram, effectnum);
2821 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2825 // 1+2+12+12+2=29 bytes
2826 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2827 MSG_WriteShort(&sv.datagram, effectnum);
2828 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2829 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2830 MSG_WriteShort(&sv.datagram, count);
2833 SV_FlushBroadcastMessages();
2836 //PF_setpause, // void(float pause) setpause = #531;
2837 static void VM_SV_setpause(prvm_prog_t *prog) {
2839 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2840 if (pauseValue != 0) { //pause the game
2842 sv.pausedstart = realtime;
2843 } else { //disable pause, in case it was enabled
2844 if (sv.paused != 0) {
2849 // send notification to all clients
2850 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2851 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2854 // #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.
2855 static void VM_SV_skel_create(prvm_prog_t *prog)
2857 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2858 dp_model_t *model = SV_GetModelByIndex(modelindex);
2859 skeleton_t *skeleton;
2861 PRVM_G_FLOAT(OFS_RETURN) = 0;
2862 if (!model || !model->num_bones)
2864 for (i = 0;i < MAX_EDICTS;i++)
2865 if (!prog->skeletons[i])
2867 if (i == MAX_EDICTS)
2869 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2870 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2871 skeleton->model = model;
2872 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2873 // initialize to identity matrices
2874 for (i = 0;i < skeleton->model->num_bones;i++)
2875 skeleton->relativetransforms[i] = identitymatrix;
2878 // #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
2879 static void VM_SV_skel_build(prvm_prog_t *prog)
2881 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2882 skeleton_t *skeleton;
2883 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2884 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2885 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2886 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2887 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2888 dp_model_t *model = SV_GetModelByIndex(modelindex);
2893 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2894 frameblend_t frameblend[MAX_FRAMEBLENDS];
2895 matrix4x4_t blendedmatrix;
2897 PRVM_G_FLOAT(OFS_RETURN) = 0;
2898 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2900 firstbone = max(0, firstbone);
2901 lastbone = min(lastbone, model->num_bones - 1);
2902 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2903 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2904 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
2905 blendfrac = 1.0f - retainfrac;
2906 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2907 frameblend[numblends].lerp *= blendfrac;
2908 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2910 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2911 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2912 for (blendindex = 0;blendindex < numblends;blendindex++)
2914 Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2915 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2917 skeleton->relativetransforms[bonenum] = blendedmatrix;
2919 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2922 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2923 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
2925 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2926 skeleton_t *skeleton;
2927 PRVM_G_FLOAT(OFS_RETURN) = 0;
2928 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2930 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2933 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2934 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
2936 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2937 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2938 skeleton_t *skeleton;
2939 PRVM_G_INT(OFS_RETURN) = 0;
2940 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2942 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2944 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
2947 // #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)
2948 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
2950 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2951 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2952 skeleton_t *skeleton;
2953 PRVM_G_FLOAT(OFS_RETURN) = 0;
2954 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2956 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2958 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2961 // #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
2962 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
2964 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2965 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2966 skeleton_t *skeleton;
2967 PRVM_G_FLOAT(OFS_RETURN) = 0;
2968 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2970 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2973 // #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)
2974 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
2976 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2977 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2978 skeleton_t *skeleton;
2980 vec3_t forward, left, up, origin;
2981 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2982 VectorClear(PRVM_clientglobalvector(v_forward));
2983 VectorClear(PRVM_clientglobalvector(v_right));
2984 VectorClear(PRVM_clientglobalvector(v_up));
2985 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2987 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2989 matrix = skeleton->relativetransforms[bonenum];
2990 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2991 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2992 VectorNegate(left, PRVM_clientglobalvector(v_right));
2993 VectorCopy(up, PRVM_clientglobalvector(v_up));
2994 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2997 // #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)
2998 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
3000 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3001 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3002 skeleton_t *skeleton;
3005 vec3_t forward, left, up, origin;
3006 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3007 VectorClear(PRVM_clientglobalvector(v_forward));
3008 VectorClear(PRVM_clientglobalvector(v_right));
3009 VectorClear(PRVM_clientglobalvector(v_up));
3010 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3012 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3014 matrix = skeleton->relativetransforms[bonenum];
3015 // convert to absolute
3016 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3019 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3021 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3022 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3023 VectorNegate(left, PRVM_clientglobalvector(v_right));
3024 VectorCopy(up, PRVM_clientglobalvector(v_up));
3025 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3028 // #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)
3029 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3031 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3032 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3033 vec3_t forward, left, up, origin;
3034 skeleton_t *skeleton;
3036 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3038 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3040 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3041 VectorNegate(PRVM_clientglobalvector(v_right), left);
3042 VectorCopy(PRVM_clientglobalvector(v_up), up);
3043 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3044 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3045 skeleton->relativetransforms[bonenum] = matrix;
3048 // #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)
3049 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3051 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3052 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3053 vec3_t forward, left, up, origin;
3054 skeleton_t *skeleton;
3057 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3059 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3061 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3062 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3063 VectorNegate(PRVM_clientglobalvector(v_right), left);
3064 VectorCopy(PRVM_clientglobalvector(v_up), up);
3065 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3066 temp = skeleton->relativetransforms[bonenum];
3067 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3070 // #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)
3071 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3073 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3074 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3075 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3077 vec3_t forward, left, up, origin;
3078 skeleton_t *skeleton;
3081 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3083 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3084 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3085 VectorNegate(PRVM_clientglobalvector(v_right), left);
3086 VectorCopy(PRVM_clientglobalvector(v_up), up);
3087 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3088 firstbone = max(0, firstbone);
3089 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3090 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3092 temp = skeleton->relativetransforms[bonenum];
3093 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3097 // #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
3098 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3100 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3101 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3102 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3103 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3105 skeleton_t *skeletondst;
3106 skeleton_t *skeletonsrc;
3107 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3109 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3111 firstbone = max(0, firstbone);
3112 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3113 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3114 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3115 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3118 // #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)
3119 static void VM_SV_skel_delete(prvm_prog_t *prog)
3121 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3122 skeleton_t *skeleton;
3123 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3126 prog->skeletons[skeletonindex] = NULL;
3129 // #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
3130 static void VM_SV_frameforname(prvm_prog_t *prog)
3132 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3133 dp_model_t *model = SV_GetModelByIndex(modelindex);
3134 const char *name = PRVM_G_STRING(OFS_PARM1);
3136 PRVM_G_FLOAT(OFS_RETURN) = -1;
3137 if (!model || !model->animscenes)
3139 for (i = 0;i < model->numframes;i++)
3141 if (!strcasecmp(model->animscenes[i].name, name))
3143 PRVM_G_FLOAT(OFS_RETURN) = i;
3149 // #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.
3150 static void VM_SV_frameduration(prvm_prog_t *prog)
3152 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3153 dp_model_t *model = SV_GetModelByIndex(modelindex);
3154 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3155 PRVM_G_FLOAT(OFS_RETURN) = 0;
3156 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3158 if (model->animscenes[framenum].framerate)
3159 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3163 prvm_builtin_t vm_sv_builtins[] = {
3164 NULL, // #0 NULL function (not callable) (QUAKE)
3165 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3166 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3167 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3168 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3169 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3170 VM_break, // #6 void() break (QUAKE)
3171 VM_random, // #7 float() random (QUAKE)
3172 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3173 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3174 VM_error, // #10 void(string e) error (QUAKE)
3175 VM_objerror, // #11 void(string e) objerror (QUAKE)
3176 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3177 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3178 VM_spawn, // #14 entity() spawn (QUAKE)
3179 VM_remove, // #15 void(entity e) remove (QUAKE)
3180 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3181 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3182 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3183 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3184 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3185 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3186 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3187 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3188 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3189 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3190 VM_ftos, // #26 string(float f) ftos (QUAKE)
3191 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3192 VM_coredump, // #28 void() coredump (QUAKE)
3193 VM_traceon, // #29 void() traceon (QUAKE)
3194 VM_traceoff, // #30 void() traceoff (QUAKE)
3195 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3196 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3197 NULL, // #33 (QUAKE)
3198 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3199 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3200 VM_rint, // #36 float(float v) rint (QUAKE)
3201 VM_floor, // #37 float(float v) floor (QUAKE)
3202 VM_ceil, // #38 float(float v) ceil (QUAKE)
3203 NULL, // #39 (QUAKE)
3204 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3205 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3206 NULL, // #42 (QUAKE)
3207 VM_fabs, // #43 float(float f) fabs (QUAKE)
3208 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3209 VM_cvar, // #45 float(string s) cvar (QUAKE)
3210 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3211 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3212 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3213 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3214 NULL, // #50 (QUAKE)
3215 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3216 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3217 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3218 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3219 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3220 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3221 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3222 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3223 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3224 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3225 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3226 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3227 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3228 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3229 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3230 NULL, // #66 (QUAKE)
3231 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3232 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3233 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3234 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3235 NULL, // #71 (QUAKE)
3236 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3237 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3238 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3239 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3240 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3241 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3242 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3243 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3244 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3245 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3246 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3247 NULL, // #83 (QUAKE)
3248 NULL, // #84 (QUAKE)
3249 NULL, // #85 (QUAKE)
3250 NULL, // #86 (QUAKE)
3251 NULL, // #87 (QUAKE)
3252 NULL, // #88 (QUAKE)
3253 NULL, // #89 (QUAKE)
3254 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3255 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3256 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3257 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3258 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3259 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3260 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3261 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3262 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3263 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3264 // FrikaC and Telejano range #100-#199
3275 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3276 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3277 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3278 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3279 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3280 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3281 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3282 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3283 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3284 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3365 // FTEQW range #200-#299
3384 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3387 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3388 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3389 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3390 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3391 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3392 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3393 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3394 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3395 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3396 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3398 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3406 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3429 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.
3430 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
3431 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3432 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3433 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)
3434 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
3435 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)
3436 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)
3437 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)
3438 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)
3439 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)
3440 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
3441 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)
3442 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
3443 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.
3466 // CSQC range #300-#399
3467 NULL, // #300 void() clearscene (EXT_CSQC)
3468 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3469 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3470 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3471 NULL, // #304 void() renderscene (EXT_CSQC)
3472 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3473 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3474 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3475 NULL, // #308 void() R_EndPolygon
3477 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3478 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3482 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3483 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3484 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3485 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3486 NULL, // #319 void(string name) freepic (EXT_CSQC)
3487 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3488 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3489 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3490 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3491 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3492 NULL, // #325 void(void) drawresetcliparea
3497 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3498 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3499 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3500 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3501 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3502 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3503 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3504 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3505 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3506 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3507 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3508 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3509 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3510 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3511 NULL, // #344 vector() getmousepos (EXT_CSQC)
3512 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3513 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3514 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3515 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3516 NULL, // #349 float() isdemo (EXT_CSQC)
3517 VM_isserver, // #350 float() isserver (EXT_CSQC)
3518 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3519 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3520 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3521 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3527 NULL, // #360 float() readbyte (EXT_CSQC)
3528 NULL, // #361 float() readchar (EXT_CSQC)
3529 NULL, // #362 float() readshort (EXT_CSQC)
3530 NULL, // #363 float() readlong (EXT_CSQC)
3531 NULL, // #364 float() readcoord (EXT_CSQC)
3532 NULL, // #365 float() readangle (EXT_CSQC)
3533 NULL, // #366 string() readstring (EXT_CSQC)
3534 NULL, // #367 float() readfloat (EXT_CSQC)
3567 // LordHavoc's range #400-#499
3568 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3569 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3570 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3571 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3572 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3573 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3574 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3575 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3576 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)
3577 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3578 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3579 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3580 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3581 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3582 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3583 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3584 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3585 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3586 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3587 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3588 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3589 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3590 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3591 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3592 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3593 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3594 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3595 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3596 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3597 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3598 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3599 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3600 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3601 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3602 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3603 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3604 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3605 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3606 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3607 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3608 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3609 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3610 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3611 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3612 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3613 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3614 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3615 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3616 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3617 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3618 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3619 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3620 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3621 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3622 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3623 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3624 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3625 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3627 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3628 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3629 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3630 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3631 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3632 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3633 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3634 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3635 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3636 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3637 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3639 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3640 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3641 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3642 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3643 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3644 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3645 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3646 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3647 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3648 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3649 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3650 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3651 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3652 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3653 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3654 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3662 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3663 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3664 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3665 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3666 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3667 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3668 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3669 VM_SV_WritePicture, // #501
3671 VM_whichpack, // #503 string(string) whichpack = #503;
3678 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3679 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3680 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3681 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)
3682 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3683 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3684 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3685 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3686 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3687 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3697 VM_loadfromdata, // #529
3698 VM_loadfromfile, // #530
3699 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3701 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3702 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3708 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3709 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3710 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3773 VM_callfunction, // #605
3774 VM_writetofile, // #606
3775 VM_isfunction, // #607
3781 VM_parseentitydata, // #613
3792 VM_SV_getextresponse, // #624 string getextresponse(void)
3795 VM_sprintf, // #627 string sprintf(string format, ...)
3796 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3797 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3807 VM_digest_hex, // #639
3811 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3813 void SVVM_init_cmd(prvm_prog_t *prog)
3818 void SVVM_reset_cmd(prvm_prog_t *prog)
3820 World_End(&sv.world);
3821 if(PRVM_serverfunction(SV_Shutdown))
3823 func_t s = PRVM_serverfunction(SV_Shutdown);
3824 PRVM_serverglobalfloat(time) = sv.time;
3825 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3826 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");