6 //============================================================================
11 const char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
24 "DP_CSQC_ENTITYWORLDOBJECT "
25 "DP_CSQC_ENTITYMODELLIGHT "
26 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
27 "DP_CSQC_MULTIFRAME_INTERPOLATION "
28 "DP_CSQC_BOXPARTICLES "
29 "DP_CSQC_SPAWNPARTICLE "
30 "DP_CSQC_QUERYRENDERENTITY "
31 "DP_CSQC_ROTATEMOVES "
44 "DP_EF_RESTARTANIM_BIT "
49 "DP_ENT_CUSTOMCOLORMAP "
50 "DP_ENT_EXTERIORMODELTOCLIENT "
53 "DP_ENT_LOWPRECISION "
55 "DP_ENT_TRAILEFFECTNUM "
57 "DP_GFX_EXTERNALTEXTURES "
58 "DP_GFX_EXTERNALTEXTURES_PERMAP "
60 "DP_GFX_MODEL_INTERPOLATION "
61 "DP_GFX_QUAKE3MODELTAGS "
65 "DP_GFX_FONTS_FREETYPE "
67 "DP_FONT_VARIABLEWIDTH "
69 "DP_HALFLIFE_MAP_CVAR "
72 "DP_LIGHTSTYLE_STATICVALUE "
76 "DP_MOVETYPEBOUNCEMISSILE "
77 "DP_MOVETYPEFLYWORLDONLY "
80 "DP_QC_ASINACOSATANATAN2TAN "
86 "DP_QC_CVAR_DEFSTRING "
87 "DP_QC_CVAR_DESCRIPTION "
91 "DP_QC_DIGEST_SHA256 "
96 "DP_QC_EXTRESPONSEPACKET "
98 "DP_QC_FINDCHAINFLAGS "
99 "DP_QC_FINDCHAINFLOAT "
100 "DP_QC_FINDCHAIN_TOFIELD "
106 "DP_QC_GETSURFACETRIANGLE "
107 "DP_QC_GETSURFACEPOINTATTRIBUTE "
109 "DP_QC_GETTAGINFO_BONEPROPERTIES "
111 "DP_QC_GETTIME_CDTRACK "
115 "DP_QC_MULTIPLETEMPSTRINGS "
116 "DP_QC_NUM_FOR_EDICT "
118 "DP_QC_SINCOSSQRTPOW "
121 "DP_QC_STRINGBUFFERS "
122 "DP_QC_STRINGBUFFERS_CVARLIST "
123 "DP_QC_STRINGCOLORFUNCTIONS "
124 "DP_QC_STRING_CASE_FUNCTIONS "
126 "DP_QC_TOKENIZEBYSEPARATOR "
127 "DP_QC_TOKENIZE_CONSOLE "
130 "DP_QC_TRACE_MOVETYPE_HITMODEL "
131 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
132 "DP_QC_UNLIMITEDTEMPSTRINGS "
136 "DP_QC_VECTOANGLES_WITH_ROLL "
137 "DP_QC_VECTORVECTORS "
144 "DP_SKELETONOBJECTS "
145 "DP_SND_DIRECTIONLESSATTNNONE "
147 "DP_SND_SOUND7_WIP1 "
148 "DP_SND_SOUND7_WIP2 "
152 "DP_SND_GETSOUNDTIME "
154 "DP_VIDEO_SUBTITLES "
158 "DP_SV_BOUNCEFACTOR "
159 "DP_SV_CLIENTCAMERA "
160 "DP_SV_CLIENTCOLORS "
163 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
164 "DP_SV_DISCARDABLEDEMO "
165 "DP_SV_DRAWONLYTOCLIENT "
168 "DP_SV_ENTITYCONTENTSTRANSITION "
169 "DP_SV_MODELFLAGS_AS_EFFECTS "
170 "DP_SV_MOVETYPESTEP_LANDEVENT "
172 "DP_SV_NODRAWTOCLIENT "
173 "DP_SV_ONENTITYNOSPAWNFUNCTION "
174 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
176 "DP_SV_PING_PACKETLOSS "
177 "DP_SV_PLAYERPHYSICS "
179 "DP_SV_POINTPARTICLES "
181 "DP_SV_PRECACHEANYTIME "
185 "DP_SV_ROTATINGBMODEL "
189 "DP_SV_SPAWNFUNC_PREFIX "
190 "DP_SV_WRITEPICTURE "
191 "DP_SV_WRITEUNTERMINATEDSTRING "
195 "DP_TE_EXPLOSIONRGB "
197 "DP_TE_PARTICLECUBE "
198 "DP_TE_PARTICLERAIN "
199 "DP_TE_PARTICLESNOW "
201 "DP_TE_QUADEFFECTS1 "
204 "DP_TE_STANDARDEFFECTBUILTINS "
205 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
209 "FTE_CSQC_SKELETONOBJECTS "
212 "KRIMZON_SV_PARSECLIENTCOMMAND "
215 "NEXUIZ_PLAYERMODEL "
217 "PRYDON_CLIENTCURSOR "
218 "TENEBRAE_GFX_DLIGHTS "
221 //"EXT_CSQC " // not ready yet
228 This is the only valid way to move an object without using the physics of the world (setting velocity and waiting). Directly changing origin will not set internal links correctly, so clipping would be messed up. This should be called when an object is spawned, and then only if it is teleported.
230 setorigin (entity, origin)
233 static void VM_SV_setorigin(prvm_prog_t *prog)
238 VM_SAFEPARMCOUNT(2, VM_setorigin);
240 e = PRVM_G_EDICT(OFS_PARM0);
241 if (e == prog->edicts)
243 VM_Warning(prog, "setorigin: can not modify world entity\n");
246 if (e->priv.server->free)
248 VM_Warning(prog, "setorigin: can not modify free entity\n");
251 org = PRVM_G_VECTOR(OFS_PARM1);
252 VectorCopy (org, PRVM_serveredictvector(e, origin));
253 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
254 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
258 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
259 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qboolean rotate)
263 for (i=0 ; i<3 ; i++)
265 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
267 // set derived values
268 VectorCopy (min, PRVM_serveredictvector(e, mins));
269 VectorCopy (max, PRVM_serveredictvector(e, maxs));
270 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
279 the size box is rotated by the current angle
280 LordHavoc: no it isn't...
282 setsize (entity, minvector, maxvector)
285 static void VM_SV_setsize(prvm_prog_t *prog)
290 VM_SAFEPARMCOUNT(3, VM_setsize);
292 e = PRVM_G_EDICT(OFS_PARM0);
293 if (e == prog->edicts)
295 VM_Warning(prog, "setsize: can not modify world entity\n");
298 if (e->priv.server->free)
300 VM_Warning(prog, "setsize: can not modify free entity\n");
303 min = PRVM_G_VECTOR(OFS_PARM1);
304 max = PRVM_G_VECTOR(OFS_PARM2);
305 SetMinMaxSize(prog, e, min, max, false);
313 setmodel(entity, model)
316 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
317 static void VM_SV_setmodel(prvm_prog_t *prog)
323 VM_SAFEPARMCOUNT(2, VM_setmodel);
325 e = PRVM_G_EDICT(OFS_PARM0);
326 if (e == prog->edicts)
328 VM_Warning(prog, "setmodel: can not modify world entity\n");
331 if (e->priv.server->free)
333 VM_Warning(prog, "setmodel: can not modify free entity\n");
336 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
337 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
338 PRVM_serveredictfloat(e, modelindex) = i;
340 mod = SV_GetModelByIndex(i);
344 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
345 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
347 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
350 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
357 single print to a specific client
359 sprint(clientent, value)
362 static void VM_SV_sprint(prvm_prog_t *prog)
366 char string[VM_STRINGTEMP_LENGTH];
368 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
370 VM_VarString(prog, 1, string, sizeof(string));
372 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
373 // LordHavoc: div0 requested that sprintto world operate like print
380 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
382 VM_Warning(prog, "tried to centerprint to a non-client\n");
386 client = svs.clients + entnum-1;
387 if (!client->netconnection)
390 MSG_WriteChar(&client->netconnection->message,svc_print);
391 MSG_WriteString(&client->netconnection->message, string);
399 single print to a specific client
401 centerprint(clientent, value)
404 static void VM_SV_centerprint(prvm_prog_t *prog)
408 char string[VM_STRINGTEMP_LENGTH];
410 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
412 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
414 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
416 VM_Warning(prog, "tried to centerprint to a non-client\n");
420 client = svs.clients + entnum-1;
421 if (!client->netconnection)
424 VM_VarString(prog, 1, string, sizeof(string));
425 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
426 MSG_WriteString(&client->netconnection->message, string);
433 particle(origin, color, count)
436 static void VM_SV_particle(prvm_prog_t *prog)
442 VM_SAFEPARMCOUNT(4, VM_SV_particle);
444 org = PRVM_G_VECTOR(OFS_PARM0);
445 dir = PRVM_G_VECTOR(OFS_PARM1);
446 color = PRVM_G_FLOAT(OFS_PARM2);
447 count = PRVM_G_FLOAT(OFS_PARM3);
448 SV_StartParticle (org, dir, (int)color, (int)count);
458 static void VM_SV_ambientsound(prvm_prog_t *prog)
462 float vol, attenuation;
465 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
467 pos = PRVM_G_VECTOR (OFS_PARM0);
468 samp = PRVM_G_STRING(OFS_PARM1);
469 vol = PRVM_G_FLOAT(OFS_PARM2);
470 attenuation = PRVM_G_FLOAT(OFS_PARM3);
472 // check to see if samp was properly precached
473 soundnum = SV_SoundIndex(samp, 1);
481 // add an svc_spawnambient command to the level signon packet
484 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
486 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
488 MSG_WriteVector(&sv.signon, pos, sv.protocol);
490 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
491 MSG_WriteShort (&sv.signon, soundnum);
493 MSG_WriteByte (&sv.signon, soundnum);
495 MSG_WriteByte (&sv.signon, (int)(vol*255));
496 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
504 Each entity can have eight independant sound sources, like voice,
507 Channel 0 is an auto-allocate channel, the others override anything
508 already running on that entity/channel pair.
510 An attenuation of 0 will play full volume everywhere in the level.
511 Larger attenuations will drop off.
515 static void VM_SV_sound(prvm_prog_t *prog)
519 prvm_edict_t *entity;
525 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
527 entity = PRVM_G_EDICT(OFS_PARM0);
528 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
529 sample = PRVM_G_STRING(OFS_PARM2);
530 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
533 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
537 attenuation = PRVM_G_FLOAT(OFS_PARM4);
541 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
546 if(channel >= 8 && channel <= 15) // weird QW feature
548 flags |= CHANFLAG_RELIABLE;
553 flags = PRVM_G_FLOAT(OFS_PARM6);
555 if (volume < 0 || volume > 255)
557 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
561 if (attenuation < 0 || attenuation > 4)
563 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
567 channel = CHAN_USER2ENGINE(channel);
569 if (!IS_CHAN(channel))
571 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
575 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE, pitchchange);
582 Follows the same logic as VM_SV_sound, except instead of
583 an entity, an origin for the sound is provided, and channel
584 is omitted (since no entity is being tracked).
588 static void VM_SV_pointsound(prvm_prog_t *prog)
596 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
598 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
599 sample = PRVM_G_STRING(OFS_PARM1);
600 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
601 attenuation = PRVM_G_FLOAT(OFS_PARM3);
602 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
604 if (volume < 0 || volume > 255)
606 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
610 if (attenuation < 0 || attenuation > 4)
612 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
616 SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
623 Used for use tracing and shot targeting
624 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
625 if the tryents flag is set.
627 traceline (vector1, vector2, movetype, ignore)
630 static void VM_SV_traceline(prvm_prog_t *prog)
637 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
639 prog->xfunction->builtinsprofile += 30;
641 v1 = PRVM_G_VECTOR(OFS_PARM0);
642 v2 = PRVM_G_VECTOR(OFS_PARM1);
643 move = (int)PRVM_G_FLOAT(OFS_PARM2);
644 ent = PRVM_G_EDICT(OFS_PARM3);
646 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]))
647 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));
649 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
651 VM_SetTraceGlobals(prog, &trace);
659 Used for use tracing and shot targeting
660 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
661 if the tryents flag is set.
663 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
666 // LordHavoc: added this for my own use, VERY useful, similar to traceline
667 static void VM_SV_tracebox(prvm_prog_t *prog)
669 float *v1, *v2, *m1, *m2;
674 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
676 prog->xfunction->builtinsprofile += 30;
678 v1 = PRVM_G_VECTOR(OFS_PARM0);
679 m1 = PRVM_G_VECTOR(OFS_PARM1);
680 m2 = PRVM_G_VECTOR(OFS_PARM2);
681 v2 = PRVM_G_VECTOR(OFS_PARM3);
682 move = (int)PRVM_G_FLOAT(OFS_PARM4);
683 ent = PRVM_G_EDICT(OFS_PARM5);
685 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]))
686 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));
688 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
690 VM_SetTraceGlobals(prog, &trace);
693 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
698 vec3_t original_origin;
699 vec3_t original_velocity;
700 vec3_t original_angles;
701 vec3_t original_avelocity;
704 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
705 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
706 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
707 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
709 gravity = PRVM_serveredictfloat(tossent, gravity);
712 gravity *= sv_gravity.value * 0.025;
714 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
716 SV_CheckVelocity (tossent);
717 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
718 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
719 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
720 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
721 trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
722 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
723 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
725 if (trace.fraction < 1)
729 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
730 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
731 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
732 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
737 static void VM_SV_tracetoss(prvm_prog_t *prog)
741 prvm_edict_t *ignore;
743 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
745 prog->xfunction->builtinsprofile += 600;
747 ent = PRVM_G_EDICT(OFS_PARM0);
748 if (ent == prog->edicts)
750 VM_Warning(prog, "tracetoss: can not use world entity\n");
753 ignore = PRVM_G_EDICT(OFS_PARM1);
755 trace = SV_Trace_Toss(prog, ent, ignore);
757 VM_SetTraceGlobals(prog, &trace);
760 //============================================================================
762 static int checkpvsbytes;
763 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
765 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
771 // cycle to the next one
773 check = bound(1, check, svs.maxclients);
774 if (check == svs.maxclients)
782 prog->xfunction->builtinsprofile++;
784 if (i == svs.maxclients+1)
786 // look up the client's edict
787 ent = PRVM_EDICT_NUM(i);
788 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
789 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
791 // found a valid client (possibly the same one again)
795 // get the PVS for the entity
796 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
798 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
799 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
808 Returns a client (or object that has a client enemy) that would be a
811 If there is more than one valid option, they are cycled each frame
813 If (self.origin + self.viewofs) is not in the PVS of the current target,
814 it is not returned at all.
819 int c_invis, c_notvis;
820 static void VM_SV_checkclient(prvm_prog_t *prog)
822 prvm_edict_t *ent, *self;
825 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
827 // find a new check if on a new frame
828 if (sv.time - sv.lastchecktime >= 0.1)
830 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
831 sv.lastchecktime = sv.time;
834 // return check if it might be visible
835 ent = PRVM_EDICT_NUM(sv.lastcheck);
836 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
838 VM_RETURN_EDICT(prog->edicts);
842 // if current entity can't possibly see the check entity, return 0
843 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
844 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
845 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
848 VM_RETURN_EDICT(prog->edicts);
852 // might be able to see it
854 VM_RETURN_EDICT(ent);
857 //============================================================================
863 Checks if an entity is in a point's PVS.
864 Should be fast but can be inexact.
866 float checkpvs(vector viewpos, entity viewee) = #240;
869 static void VM_SV_checkpvs(prvm_prog_t *prog)
872 prvm_edict_t *viewee;
877 unsigned char fatpvs[MAX_MAP_LEAFS/8];
880 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
881 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
882 viewee = PRVM_G_EDICT(OFS_PARM1);
884 if(viewee->priv.server->free)
886 VM_Warning(prog, "checkpvs: can not check free entity\n");
887 PRVM_G_FLOAT(OFS_RETURN) = 4;
892 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
894 // no PVS support on this worldmodel... darn
895 PRVM_G_FLOAT(OFS_RETURN) = 3;
898 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
901 // viewpos isn't in any PVS... darn
902 PRVM_G_FLOAT(OFS_RETURN) = 2;
905 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
907 // using fat PVS like FTEQW does (slow)
908 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
910 // no PVS support on this worldmodel... darn
911 PRVM_G_FLOAT(OFS_RETURN) = 3;
914 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
917 // viewpos isn't in any PVS... darn
918 PRVM_G_FLOAT(OFS_RETURN) = 2;
921 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
930 Sends text over to the client's execution buffer
932 stuffcmd (clientent, value, ...)
935 static void VM_SV_stuffcmd(prvm_prog_t *prog)
939 char string[VM_STRINGTEMP_LENGTH];
941 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
943 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
944 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
946 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
950 VM_VarString(prog, 1, string, sizeof(string));
953 host_client = svs.clients + entnum-1;
954 Host_ClientCommands ("%s", string);
962 Returns a chain of entities that have origins within a spherical area
964 findradius (origin, radius)
967 static void VM_SV_findradius(prvm_prog_t *prog)
969 prvm_edict_t *ent, *chain;
970 vec_t radius, radius2;
971 vec3_t org, eorg, mins, maxs;
974 static prvm_edict_t *touchedicts[MAX_EDICTS];
977 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
980 chainfield = PRVM_G_INT(OFS_PARM2);
982 chainfield = prog->fieldoffsets.chain;
984 prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
986 chain = (prvm_edict_t *)prog->edicts;
988 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
989 radius = PRVM_G_FLOAT(OFS_PARM1);
990 radius2 = radius * radius;
992 mins[0] = org[0] - (radius + 1);
993 mins[1] = org[1] - (radius + 1);
994 mins[2] = org[2] - (radius + 1);
995 maxs[0] = org[0] + (radius + 1);
996 maxs[1] = org[1] + (radius + 1);
997 maxs[2] = org[2] + (radius + 1);
998 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
999 if (numtouchedicts > MAX_EDICTS)
1001 // this never happens
1002 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1003 numtouchedicts = MAX_EDICTS;
1005 for (i = 0;i < numtouchedicts;i++)
1007 ent = touchedicts[i];
1008 prog->xfunction->builtinsprofile++;
1009 // Quake did not return non-solid entities but darkplaces does
1010 // (note: this is the reason you can't blow up fallen zombies)
1011 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1013 // LordHavoc: compare against bounding box rather than center so it
1014 // doesn't miss large objects, and use DotProduct instead of Length
1015 // for a major speedup
1016 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1017 if (sv_gameplayfix_findradiusdistancetobox.integer)
1019 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1020 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1021 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1024 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1025 if (DotProduct(eorg, eorg) < radius2)
1027 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1032 VM_RETURN_EDICT(chain);
1035 static void VM_SV_precache_sound(prvm_prog_t *prog)
1037 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1038 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1041 static void VM_SV_precache_model(prvm_prog_t *prog)
1043 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1044 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1045 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1052 float(float yaw, float dist[, settrace]) walkmove
1055 static void VM_SV_walkmove(prvm_prog_t *prog)
1064 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1066 // assume failure if it returns early
1067 PRVM_G_FLOAT(OFS_RETURN) = 0;
1069 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1070 if (ent == prog->edicts)
1072 VM_Warning(prog, "walkmove: can not modify world entity\n");
1075 if (ent->priv.server->free)
1077 VM_Warning(prog, "walkmove: can not modify free entity\n");
1080 yaw = PRVM_G_FLOAT(OFS_PARM0);
1081 dist = PRVM_G_FLOAT(OFS_PARM1);
1082 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1084 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1087 yaw = yaw*M_PI*2 / 360;
1089 move[0] = cos(yaw)*dist;
1090 move[1] = sin(yaw)*dist;
1093 // save program state, because SV_movestep may call other progs
1094 oldf = prog->xfunction;
1095 oldself = PRVM_serverglobaledict(self);
1097 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1100 // restore program state
1101 prog->xfunction = oldf;
1102 PRVM_serverglobaledict(self) = oldself;
1113 static void VM_SV_droptofloor(prvm_prog_t *prog)
1119 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1121 // assume failure if it returns early
1122 PRVM_G_FLOAT(OFS_RETURN) = 0;
1124 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1125 if (ent == prog->edicts)
1127 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1130 if (ent->priv.server->free)
1132 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1136 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1139 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1140 if (sv_gameplayfix_unstickentities.integer)
1141 SV_UnstickEntity(ent);
1143 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1144 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1147 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]);
1148 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1149 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1150 VectorSubtract(trace.endpos, offset, trace.endpos);
1151 if (trace.startsolid)
1153 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]);
1154 if (sv_gameplayfix_unstickentities.integer)
1155 SV_UnstickEntity(ent);
1157 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1158 PRVM_serveredictedict(ent, groundentity) = 0;
1159 PRVM_G_FLOAT(OFS_RETURN) = 1;
1161 else if (trace.fraction < 1)
1163 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]);
1164 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1165 if (sv_gameplayfix_unstickentities.integer)
1166 SV_UnstickEntity(ent);
1168 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1169 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1170 PRVM_G_FLOAT(OFS_RETURN) = 1;
1171 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1172 ent->priv.server->suspendedinairflag = true;
1177 if (trace.fraction != 1)
1179 if (trace.fraction < 1)
1180 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1182 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1183 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1184 PRVM_G_FLOAT(OFS_RETURN) = 1;
1185 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1186 ent->priv.server->suspendedinairflag = true;
1195 void(float style, string value) lightstyle
1198 static void VM_SV_lightstyle(prvm_prog_t *prog)
1205 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1207 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1208 val = PRVM_G_STRING(OFS_PARM1);
1210 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1211 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1214 // change the string in sv
1215 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1217 // send message to all clients on this server
1218 if (sv.state != ss_active)
1221 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1223 if (client->active && client->netconnection)
1225 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1226 MSG_WriteChar (&client->netconnection->message,style);
1227 MSG_WriteString (&client->netconnection->message, val);
1237 static void VM_SV_checkbottom(prvm_prog_t *prog)
1239 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1240 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1248 static void VM_SV_pointcontents(prvm_prog_t *prog)
1250 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1251 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1258 Pick a vector for the player to shoot along
1259 vector aim(entity, missilespeed)
1262 static void VM_SV_aim(prvm_prog_t *prog)
1264 prvm_edict_t *ent, *check, *bestent;
1265 vec3_t start, dir, end, bestdir;
1268 float dist, bestdist;
1271 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1273 // assume failure if it returns early
1274 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1275 // if sv_aim is so high it can't possibly accept anything, skip out early
1276 if (sv_aim.value >= 1)
1279 ent = PRVM_G_EDICT(OFS_PARM0);
1280 if (ent == prog->edicts)
1282 VM_Warning(prog, "aim: can not use world entity\n");
1285 if (ent->priv.server->free)
1287 VM_Warning(prog, "aim: can not use free entity\n");
1290 //speed = PRVM_G_FLOAT(OFS_PARM1);
1292 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1295 // try sending a trace straight
1296 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1297 VectorMA (start, 2048, dir, end);
1298 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1299 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1300 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1302 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1307 // try all possible entities
1308 VectorCopy (dir, bestdir);
1309 bestdist = sv_aim.value;
1312 check = PRVM_NEXT_EDICT(prog->edicts);
1313 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1315 prog->xfunction->builtinsprofile++;
1316 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1320 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1321 continue; // don't aim at teammate
1322 for (j=0 ; j<3 ; j++)
1323 end[j] = PRVM_serveredictvector(check, origin)[j]
1324 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1325 VectorSubtract (end, start, dir);
1326 VectorNormalize (dir);
1327 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1328 if (dist < bestdist)
1329 continue; // to far to turn
1330 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1331 if (tr.ent == check)
1332 { // can shoot at this one
1340 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1341 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1342 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1344 VectorNormalize (end);
1345 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1349 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1354 ===============================================================================
1358 ===============================================================================
1361 #define MSG_BROADCAST 0 // unreliable to all
1362 #define MSG_ONE 1 // reliable to one (msg_entity)
1363 #define MSG_ALL 2 // reliable to all
1364 #define MSG_INIT 3 // write to the init string
1365 #define MSG_ENTITY 5
1367 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1373 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1377 return &sv.datagram;
1380 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1381 entnum = PRVM_NUM_FOR_EDICT(ent);
1382 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1384 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1385 return &sv.reliable_datagram;
1388 return &svs.clients[entnum-1].netconnection->message;
1391 VM_Warning(prog, "WriteDest: bad destination\n");
1393 return &sv.reliable_datagram;
1399 return sv.writeentitiestoclient_msg;
1405 static void VM_SV_WriteByte(prvm_prog_t *prog)
1407 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1408 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1411 static void VM_SV_WriteChar(prvm_prog_t *prog)
1413 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1414 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1417 static void VM_SV_WriteShort(prvm_prog_t *prog)
1419 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1420 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1423 static void VM_SV_WriteLong(prvm_prog_t *prog)
1425 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1426 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1429 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1431 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1432 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1435 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1437 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1438 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1441 static void VM_SV_WriteString(prvm_prog_t *prog)
1443 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1444 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1447 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1449 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1450 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1454 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1456 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1457 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1460 // writes a picture as at most size bytes of data
1462 // IMGNAME \0 SIZE(short) IMGDATA
1463 // if failed to read/compress:
1465 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1466 static void VM_SV_WritePicture(prvm_prog_t *prog)
1468 const char *imgname;
1472 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1474 imgname = PRVM_G_STRING(OFS_PARM1);
1475 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1479 MSG_WriteString(WriteDest(prog), imgname);
1480 if(Image_Compress(imgname, size, &buf, &size))
1483 MSG_WriteShort(WriteDest(prog), size);
1484 SZ_Write(WriteDest(prog), (unsigned char *) buf, size);
1489 MSG_WriteShort(WriteDest(prog), 0);
1493 //////////////////////////////////////////////////////////
1495 static void VM_SV_makestatic(prvm_prog_t *prog)
1500 // allow 0 parameters due to an id1 qc bug in which this function is used
1501 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1502 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1504 if (prog->argc >= 1)
1505 ent = PRVM_G_EDICT(OFS_PARM0);
1507 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1508 if (ent == prog->edicts)
1510 VM_Warning(prog, "makestatic: can not modify world entity\n");
1513 if (ent->priv.server->free)
1515 VM_Warning(prog, "makestatic: can not modify free entity\n");
1520 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1525 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1526 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1527 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1529 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1531 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1532 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1533 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1537 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1538 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1539 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1542 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1543 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1544 for (i=0 ; i<3 ; i++)
1546 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1547 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1550 // throw the entity away now
1551 PRVM_ED_Free(prog, ent);
1554 //=============================================================================
1561 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1567 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1569 ent = PRVM_G_EDICT(OFS_PARM0);
1570 i = PRVM_NUM_FOR_EDICT(ent);
1571 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1573 Con_Print("tried to setspawnparms on a non-client\n");
1577 // copy spawn parms out of the client_t
1578 client = svs.clients + i-1;
1579 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1580 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1587 Returns a color vector indicating the lighting at the requested point.
1589 (Internal Operation note: actually measures the light beneath the point, just like
1590 the model lighting on the client)
1595 static void VM_SV_getlight(prvm_prog_t *prog)
1597 vec3_t ambientcolor, diffusecolor, diffusenormal;
1599 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1600 p = PRVM_G_VECTOR(OFS_PARM0);
1601 VectorClear(ambientcolor);
1602 VectorClear(diffusecolor);
1603 VectorClear(diffusenormal);
1604 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1605 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1606 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1611 unsigned char type; // 1/2/8 or other value if isn't used
1615 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1616 static int vm_customstats_last;
1618 void VM_CustomStats_Clear (void)
1622 Z_Free(vm_customstats);
1623 vm_customstats = NULL;
1624 vm_customstats_last = -1;
1628 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1630 prvm_prog_t *prog = SVVM_prog;
1637 for(i=0; i<vm_customstats_last+1 ;i++)
1639 if(!vm_customstats[i].type)
1641 switch(vm_customstats[i].type)
1643 //string as 16 bytes
1646 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1647 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1648 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1649 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1650 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1652 //float field sent as-is
1654 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1656 //integer value of float field
1658 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1666 // void(float index, float type, .void field) SV_AddStat = #232;
1667 // Set up an auto-sent player stat.
1668 // Client's get thier own fields sent to them. Index may not be less than 32.
1669 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1670 // 1: string (4 stats carrying a total of 16 charactures)
1671 // 2: float (one stat, float converted to an integer for transportation)
1672 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1673 static void VM_SV_AddStat(prvm_prog_t *prog)
1678 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1682 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1685 VM_Warning(prog, "PF_SV_AddStat: not enough memory\n");
1689 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1690 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1691 off = PRVM_G_INT (OFS_PARM2);
1696 VM_Warning(prog, "PF_SV_AddStat: index may not be less than 32\n");
1699 if(i >= (MAX_CL_STATS-32))
1701 VM_Warning(prog, "PF_SV_AddStat: index >= MAX_CL_STATS\n");
1704 if(i > (MAX_CL_STATS-32-4) && type == 1)
1706 VM_Warning(prog, "PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1709 vm_customstats[i].type = type;
1710 vm_customstats[i].fieldoffset = off;
1711 if(vm_customstats_last < i)
1712 vm_customstats_last = i;
1719 copies data from one entity to another
1721 copyentity(src, dst)
1724 static void VM_SV_copyentity(prvm_prog_t *prog)
1726 prvm_edict_t *in, *out;
1727 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1728 in = PRVM_G_EDICT(OFS_PARM0);
1729 if (in == prog->edicts)
1731 VM_Warning(prog, "copyentity: can not read world entity\n");
1734 if (in->priv.server->free)
1736 VM_Warning(prog, "copyentity: can not read free entity\n");
1739 out = PRVM_G_EDICT(OFS_PARM1);
1740 if (out == prog->edicts)
1742 VM_Warning(prog, "copyentity: can not modify world entity\n");
1745 if (out->priv.server->free)
1747 VM_Warning(prog, "copyentity: can not modify free entity\n");
1750 memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
1759 sets the color of a client and broadcasts the update to all connected clients
1761 setcolor(clientent, value)
1764 static void VM_SV_setcolor(prvm_prog_t *prog)
1769 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1770 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1771 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1773 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1775 Con_Print("tried to setcolor a non-client\n");
1779 client = svs.clients + entnum-1;
1782 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1783 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1786 if (client->old_colors != client->colors)
1788 client->old_colors = client->colors;
1789 // send notification to all clients
1790 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1791 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1792 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1800 effect(origin, modelname, startframe, framecount, framerate)
1803 static void VM_SV_effect(prvm_prog_t *prog)
1807 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1808 s = PRVM_G_STRING(OFS_PARM1);
1811 VM_Warning(prog, "effect: no model specified\n");
1815 i = SV_ModelIndex(s, 1);
1818 VM_Warning(prog, "effect: model not precached\n");
1822 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1824 VM_Warning(prog, "effect: framecount < 1\n");
1828 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1830 VM_Warning(prog, "effect: framerate < 1\n");
1834 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));
1837 static void VM_SV_te_blood(prvm_prog_t *prog)
1839 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1840 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1842 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1843 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1845 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1847 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1849 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1850 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1851 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1853 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1854 SV_FlushBroadcastMessages();
1857 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1859 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1860 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1862 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1863 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1865 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1866 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1869 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1870 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1873 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1875 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1876 SV_FlushBroadcastMessages();
1879 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1881 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1882 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1883 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1885 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1886 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1887 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1889 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1890 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1891 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1892 SV_FlushBroadcastMessages();
1895 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1897 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1898 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1900 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1901 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1911 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1912 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1913 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1915 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1917 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1918 // gravity true/false
1919 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1921 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1922 SV_FlushBroadcastMessages();
1925 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1927 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1928 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1930 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1931 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1934 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1941 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1942 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1943 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1945 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1947 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1948 SV_FlushBroadcastMessages();
1951 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1953 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1954 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1956 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1957 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1964 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1965 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1971 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1973 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1974 SV_FlushBroadcastMessages();
1977 static void VM_SV_te_spark(prvm_prog_t *prog)
1979 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1980 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1982 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1983 MSG_WriteByte(&sv.datagram, TE_SPARK);
1985 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1989 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1990 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1991 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1993 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1994 SV_FlushBroadcastMessages();
1997 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
1999 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2000 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2001 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2004 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2005 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2006 SV_FlushBroadcastMessages();
2009 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2011 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2012 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2013 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2015 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2016 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2017 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2018 SV_FlushBroadcastMessages();
2021 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2023 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2024 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2025 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2028 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2029 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2030 SV_FlushBroadcastMessages();
2033 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2035 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2036 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2037 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2039 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2040 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2041 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2042 SV_FlushBroadcastMessages();
2045 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2047 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2048 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2049 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2052 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2054 SV_FlushBroadcastMessages();
2057 static void VM_SV_te_customflash(prvm_prog_t *prog)
2059 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2060 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2062 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2063 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2065 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2066 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2067 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2069 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2071 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2073 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2074 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2075 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2076 SV_FlushBroadcastMessages();
2079 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2081 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2082 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2083 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2085 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2086 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2087 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2088 SV_FlushBroadcastMessages();
2091 static void VM_SV_te_spike(prvm_prog_t *prog)
2093 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2094 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2095 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2097 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2098 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2099 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2100 SV_FlushBroadcastMessages();
2103 static void VM_SV_te_superspike(prvm_prog_t *prog)
2105 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2106 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2107 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2109 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2110 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2111 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2112 SV_FlushBroadcastMessages();
2115 static void VM_SV_te_explosion(prvm_prog_t *prog)
2117 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2118 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2119 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2121 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2122 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2123 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2124 SV_FlushBroadcastMessages();
2127 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2129 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2130 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2131 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2133 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2134 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2135 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2136 SV_FlushBroadcastMessages();
2139 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2141 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2142 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2143 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2145 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2146 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2147 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2148 SV_FlushBroadcastMessages();
2151 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2153 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2154 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2155 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2157 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2158 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2159 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2160 SV_FlushBroadcastMessages();
2163 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2165 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2166 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2167 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2169 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2170 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2171 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2172 SV_FlushBroadcastMessages();
2175 static void VM_SV_te_teleport(prvm_prog_t *prog)
2177 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2178 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2179 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2181 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2182 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2183 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2184 SV_FlushBroadcastMessages();
2187 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2189 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2190 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2191 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2193 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2194 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2195 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2197 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2198 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2199 SV_FlushBroadcastMessages();
2202 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2204 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2205 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2206 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2208 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2210 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2211 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2212 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2214 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2215 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2216 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2217 SV_FlushBroadcastMessages();
2220 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2222 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2223 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2224 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2226 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2230 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2232 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2234 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2235 SV_FlushBroadcastMessages();
2238 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2240 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2241 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2242 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2244 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2246 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2247 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2248 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2250 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2251 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2252 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2253 SV_FlushBroadcastMessages();
2256 static void VM_SV_te_beam(prvm_prog_t *prog)
2258 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2259 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2260 MSG_WriteByte(&sv.datagram, TE_BEAM);
2262 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2264 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2265 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2266 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2268 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2269 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2270 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2271 SV_FlushBroadcastMessages();
2274 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2276 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2277 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2278 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2279 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2280 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2281 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2282 SV_FlushBroadcastMessages();
2285 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2287 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2288 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2289 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2291 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2292 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2293 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2295 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2296 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2297 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2299 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2300 SV_FlushBroadcastMessages();
2303 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2304 //this function originally written by KrimZon, made shorter by LordHavoc
2305 static void VM_SV_clientcommand(prvm_prog_t *prog)
2307 client_t *temp_client;
2309 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2311 //find client for this entity
2312 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2313 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2315 Con_Print("PF_clientcommand: entity is not a client\n");
2319 temp_client = host_client;
2320 host_client = svs.clients + i;
2321 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
2322 host_client = temp_client;
2325 //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)
2326 static void VM_SV_setattachment(prvm_prog_t *prog)
2328 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2329 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2330 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2333 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2335 if (e == prog->edicts)
2337 VM_Warning(prog, "setattachment: can not modify world entity\n");
2340 if (e->priv.server->free)
2342 VM_Warning(prog, "setattachment: can not modify free entity\n");
2346 if (tagentity == NULL)
2347 tagentity = prog->edicts;
2351 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2353 model = SV_GetModelFromEdict(tagentity);
2356 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2358 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);
2361 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));
2364 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2365 PRVM_serveredictfloat(e, tag_index) = tagindex;
2368 /////////////////////////////////////////
2369 // DP_MD3_TAGINFO extension coded by VorteX
2371 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2375 i = (int)PRVM_serveredictfloat(e, modelindex);
2376 if (i < 1 || i >= MAX_MODELS)
2379 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2382 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2389 Matrix4x4_CreateIdentity(tag_localmatrix);
2391 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2393 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2404 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2407 float pitchsign = 1;
2409 scale = PRVM_serveredictfloat(ent, scale);
2414 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);
2417 pitchsign = SV_GetPitchSign(prog, ent);
2418 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);
2422 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2425 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2427 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2428 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2429 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2430 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2432 *out = identitymatrix;
2436 // Warnings/errors code:
2437 // 0 - normal (everything all-right)
2440 // 3 - null or non-precached model
2441 // 4 - no tags with requested index
2442 // 5 - runaway loop at attachment chain
2443 extern cvar_t cl_bob;
2444 extern cvar_t cl_bobcycle;
2445 extern cvar_t cl_bobup;
2446 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2449 int modelindex, attachloop;
2450 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2453 *out = identitymatrix; // warnings and errors return identical matrix
2455 if (ent == prog->edicts)
2457 if (ent->priv.server->free)
2460 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2461 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2464 model = SV_GetModelByIndex(modelindex);
2466 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2467 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2468 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2470 tagmatrix = identitymatrix;
2471 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2475 if (attachloop >= 256) // prevent runaway looping
2477 // apply transformation by child's tagindex on parent entity and then
2478 // by parent entity itself
2479 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2480 if (ret && attachloop == 0)
2482 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2483 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2484 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2485 // next iteration we process the parent entity
2486 if (PRVM_serveredictedict(ent, tag_entity))
2488 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2489 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2496 // RENDER_VIEWMODEL magic
2497 if (PRVM_serveredictedict(ent, viewmodelforclient))
2499 Matrix4x4_Copy(&tagmatrix, out);
2500 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2502 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2503 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2506 // Cl_bob, ported from rendering code
2507 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2510 // LordHavoc: this code is *weird*, but not replacable (I think it
2511 // should be done in QC on the server, but oh well, quake is quake)
2512 // LordHavoc: figured out bobup: the time at which the sin is at 180
2513 // degrees (which allows lengthening or squishing the peak or valley)
2514 cycle = sv.time/cl_bobcycle.value;
2515 cycle -= (int)cycle;
2516 if (cycle < cl_bobup.value)
2517 cycle = sin(M_PI * cycle / cl_bobup.value);
2519 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2520 // bob is proportional to velocity in the xy plane
2521 // (don't count Z, or jumping messes it up)
2522 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;
2523 bob = bob*0.3 + bob*0.7*cycle;
2524 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2531 //float(entity ent, string tagname) gettagindex;
2533 static void VM_SV_gettagindex(prvm_prog_t *prog)
2536 const char *tag_name;
2539 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2541 ent = PRVM_G_EDICT(OFS_PARM0);
2542 tag_name = PRVM_G_STRING(OFS_PARM1);
2544 if (ent == prog->edicts)
2546 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2549 if (ent->priv.server->free)
2551 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2556 if (!SV_GetModelFromEdict(ent))
2557 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2560 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2562 if(developer_extra.integer)
2563 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2565 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2568 //vector(entity ent, float tagindex) gettaginfo;
2569 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2573 matrix4x4_t tag_matrix;
2574 matrix4x4_t tag_localmatrix;
2576 const char *tagname;
2578 vec3_t fo, le, up, trans;
2579 const dp_model_t *model;
2581 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2583 e = PRVM_G_EDICT(OFS_PARM0);
2584 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2586 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2587 Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
2588 VectorScale(le, -1, PRVM_serverglobalvector(v_right));
2589 model = SV_GetModelFromEdict(e);
2590 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2591 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
2592 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2593 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2594 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2596 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2597 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2598 VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
2599 VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
2600 VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
2601 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2606 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2609 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2612 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2615 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2618 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2623 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2624 static void VM_SV_dropclient(prvm_prog_t *prog)
2627 client_t *oldhostclient;
2628 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2629 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2630 if (clientnum < 0 || clientnum >= svs.maxclients)
2632 VM_Warning(prog, "dropclient: not a client\n");
2635 if (!svs.clients[clientnum].active)
2637 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2640 oldhostclient = host_client;
2641 host_client = svs.clients + clientnum;
2642 SV_DropClient(false);
2643 host_client = oldhostclient;
2646 //entity() spawnclient (DP_SV_BOTCLIENT)
2647 static void VM_SV_spawnclient(prvm_prog_t *prog)
2651 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2652 prog->xfunction->builtinsprofile += 2;
2654 for (i = 0;i < svs.maxclients;i++)
2656 if (!svs.clients[i].active)
2658 prog->xfunction->builtinsprofile += 100;
2659 SV_ConnectClient (i, NULL);
2660 // this has to be set or else ClientDisconnect won't be called
2661 // we assume the qc will call ClientConnect...
2662 svs.clients[i].clientconnectcalled = true;
2663 ed = PRVM_EDICT_NUM(i + 1);
2667 VM_RETURN_EDICT(ed);
2670 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2671 static void VM_SV_clienttype(prvm_prog_t *prog)
2674 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2675 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2676 if (clientnum < 0 || clientnum >= svs.maxclients)
2677 PRVM_G_FLOAT(OFS_RETURN) = 3;
2678 else if (!svs.clients[clientnum].active)
2679 PRVM_G_FLOAT(OFS_RETURN) = 0;
2680 else if (svs.clients[clientnum].netconnection)
2681 PRVM_G_FLOAT(OFS_RETURN) = 1;
2683 PRVM_G_FLOAT(OFS_RETURN) = 2;
2690 string(string key) serverkey
2693 static void VM_SV_serverkey(prvm_prog_t *prog)
2695 char string[VM_STRINGTEMP_LENGTH];
2696 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2697 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2698 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2701 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2702 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2707 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2709 e = PRVM_G_EDICT(OFS_PARM0);
2710 if (e == prog->edicts)
2712 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2715 if (e->priv.server->free)
2717 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2720 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2721 if (i <= 0 || i >= MAX_MODELS)
2723 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2726 if (!sv.model_precache[i][0])
2728 VM_Warning(prog, "setmodelindex: model not precached\n");
2732 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2733 PRVM_serveredictfloat(e, modelindex) = i;
2735 mod = SV_GetModelByIndex(i);
2739 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2740 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2742 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2745 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2748 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2749 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2752 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2754 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2756 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2757 if (i <= 0 || i >= MAX_MODELS)
2759 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2762 if (!sv.model_precache[i][0])
2764 VM_Warning(prog, "modelnameforindex: model not precached\n");
2768 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2771 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2772 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2775 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2776 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2779 PRVM_G_FLOAT(OFS_RETURN) = i;
2782 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2783 static void VM_SV_trailparticles(prvm_prog_t *prog)
2785 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2787 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2790 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2791 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2792 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2793 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2794 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2795 SV_FlushBroadcastMessages();
2798 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2799 static void VM_SV_pointparticles(prvm_prog_t *prog)
2801 int effectnum, count;
2803 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2805 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2808 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2809 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2810 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2811 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2812 if (count == 1 && !VectorLength2(vel))
2815 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2816 MSG_WriteShort(&sv.datagram, effectnum);
2817 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2821 // 1+2+12+12+2=29 bytes
2822 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2823 MSG_WriteShort(&sv.datagram, effectnum);
2824 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2825 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2826 MSG_WriteShort(&sv.datagram, count);
2829 SV_FlushBroadcastMessages();
2832 //PF_setpause, // void(float pause) setpause = #531;
2833 static void VM_SV_setpause(prvm_prog_t *prog) {
2835 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2836 if (pauseValue != 0) { //pause the game
2838 sv.pausedstart = realtime;
2839 } else { //disable pause, in case it was enabled
2840 if (sv.paused != 0) {
2845 // send notification to all clients
2846 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2847 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2850 // #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.
2851 static void VM_SV_skel_create(prvm_prog_t *prog)
2853 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2854 dp_model_t *model = SV_GetModelByIndex(modelindex);
2855 skeleton_t *skeleton;
2857 PRVM_G_FLOAT(OFS_RETURN) = 0;
2858 if (!model || !model->num_bones)
2860 for (i = 0;i < MAX_EDICTS;i++)
2861 if (!prog->skeletons[i])
2863 if (i == MAX_EDICTS)
2865 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2866 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2867 skeleton->model = model;
2868 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2869 // initialize to identity matrices
2870 for (i = 0;i < skeleton->model->num_bones;i++)
2871 skeleton->relativetransforms[i] = identitymatrix;
2874 // #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
2875 static void VM_SV_skel_build(prvm_prog_t *prog)
2877 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2878 skeleton_t *skeleton;
2879 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2880 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2881 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2882 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2883 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2884 dp_model_t *model = SV_GetModelByIndex(modelindex);
2889 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2890 frameblend_t frameblend[MAX_FRAMEBLENDS];
2891 matrix4x4_t blendedmatrix;
2893 PRVM_G_FLOAT(OFS_RETURN) = 0;
2894 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2896 firstbone = max(0, firstbone);
2897 lastbone = min(lastbone, model->num_bones - 1);
2898 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2899 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2900 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
2901 blendfrac = 1.0f - retainfrac;
2902 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2903 frameblend[numblends].lerp *= blendfrac;
2904 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2906 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2907 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2908 for (blendindex = 0;blendindex < numblends;blendindex++)
2910 Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2911 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2913 skeleton->relativetransforms[bonenum] = blendedmatrix;
2915 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2918 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2919 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
2921 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2922 skeleton_t *skeleton;
2923 PRVM_G_FLOAT(OFS_RETURN) = 0;
2924 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2926 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2929 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2930 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
2932 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2933 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2934 skeleton_t *skeleton;
2935 PRVM_G_INT(OFS_RETURN) = 0;
2936 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2938 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2940 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
2943 // #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)
2944 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
2946 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2947 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2948 skeleton_t *skeleton;
2949 PRVM_G_FLOAT(OFS_RETURN) = 0;
2950 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2952 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2954 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2957 // #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
2958 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
2960 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2961 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2962 skeleton_t *skeleton;
2963 PRVM_G_FLOAT(OFS_RETURN) = 0;
2964 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2966 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2969 // #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)
2970 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
2972 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2973 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2974 skeleton_t *skeleton;
2976 vec3_t forward, left, up, origin;
2977 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2978 VectorClear(PRVM_clientglobalvector(v_forward));
2979 VectorClear(PRVM_clientglobalvector(v_right));
2980 VectorClear(PRVM_clientglobalvector(v_up));
2981 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2983 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2985 matrix = skeleton->relativetransforms[bonenum];
2986 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2987 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2988 VectorNegate(left, PRVM_clientglobalvector(v_right));
2989 VectorCopy(up, PRVM_clientglobalvector(v_up));
2990 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2993 // #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)
2994 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
2996 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2997 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2998 skeleton_t *skeleton;
3001 vec3_t forward, left, up, origin;
3002 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3003 VectorClear(PRVM_clientglobalvector(v_forward));
3004 VectorClear(PRVM_clientglobalvector(v_right));
3005 VectorClear(PRVM_clientglobalvector(v_up));
3006 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3008 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3010 matrix = skeleton->relativetransforms[bonenum];
3011 // convert to absolute
3012 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3015 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3017 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3018 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3019 VectorNegate(left, PRVM_clientglobalvector(v_right));
3020 VectorCopy(up, PRVM_clientglobalvector(v_up));
3021 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3024 // #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)
3025 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3027 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3028 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3029 vec3_t forward, left, up, origin;
3030 skeleton_t *skeleton;
3032 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3034 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3036 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3037 VectorNegate(PRVM_clientglobalvector(v_right), left);
3038 VectorCopy(PRVM_clientglobalvector(v_up), up);
3039 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3040 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3041 skeleton->relativetransforms[bonenum] = matrix;
3044 // #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)
3045 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3047 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3048 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3049 vec3_t forward, left, up, origin;
3050 skeleton_t *skeleton;
3053 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3055 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3057 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3058 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3059 VectorNegate(PRVM_clientglobalvector(v_right), left);
3060 VectorCopy(PRVM_clientglobalvector(v_up), up);
3061 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3062 temp = skeleton->relativetransforms[bonenum];
3063 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3066 // #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)
3067 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3069 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3070 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3071 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3073 vec3_t forward, left, up, origin;
3074 skeleton_t *skeleton;
3077 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3079 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3080 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3081 VectorNegate(PRVM_clientglobalvector(v_right), left);
3082 VectorCopy(PRVM_clientglobalvector(v_up), up);
3083 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3084 firstbone = max(0, firstbone);
3085 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3086 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3088 temp = skeleton->relativetransforms[bonenum];
3089 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3093 // #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
3094 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3096 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3097 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3098 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3099 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3101 skeleton_t *skeletondst;
3102 skeleton_t *skeletonsrc;
3103 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3105 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3107 firstbone = max(0, firstbone);
3108 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3109 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3110 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3111 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3114 // #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)
3115 static void VM_SV_skel_delete(prvm_prog_t *prog)
3117 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3118 skeleton_t *skeleton;
3119 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3122 prog->skeletons[skeletonindex] = NULL;
3125 // #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
3126 static void VM_SV_frameforname(prvm_prog_t *prog)
3128 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3129 dp_model_t *model = SV_GetModelByIndex(modelindex);
3130 const char *name = PRVM_G_STRING(OFS_PARM1);
3132 PRVM_G_FLOAT(OFS_RETURN) = -1;
3133 if (!model || !model->animscenes)
3135 for (i = 0;i < model->numframes;i++)
3137 if (!strcasecmp(model->animscenes[i].name, name))
3139 PRVM_G_FLOAT(OFS_RETURN) = i;
3145 // #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.
3146 static void VM_SV_frameduration(prvm_prog_t *prog)
3148 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3149 dp_model_t *model = SV_GetModelByIndex(modelindex);
3150 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3151 PRVM_G_FLOAT(OFS_RETURN) = 0;
3152 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3154 if (model->animscenes[framenum].framerate)
3155 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3159 prvm_builtin_t vm_sv_builtins[] = {
3160 NULL, // #0 NULL function (not callable) (QUAKE)
3161 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3162 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3163 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3164 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3165 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3166 VM_break, // #6 void() break (QUAKE)
3167 VM_random, // #7 float() random (QUAKE)
3168 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3169 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3170 VM_error, // #10 void(string e) error (QUAKE)
3171 VM_objerror, // #11 void(string e) objerror (QUAKE)
3172 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3173 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3174 VM_spawn, // #14 entity() spawn (QUAKE)
3175 VM_remove, // #15 void(entity e) remove (QUAKE)
3176 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3177 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3178 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3179 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3180 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3181 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3182 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3183 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3184 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3185 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3186 VM_ftos, // #26 string(float f) ftos (QUAKE)
3187 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3188 VM_coredump, // #28 void() coredump (QUAKE)
3189 VM_traceon, // #29 void() traceon (QUAKE)
3190 VM_traceoff, // #30 void() traceoff (QUAKE)
3191 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3192 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3193 NULL, // #33 (QUAKE)
3194 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3195 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3196 VM_rint, // #36 float(float v) rint (QUAKE)
3197 VM_floor, // #37 float(float v) floor (QUAKE)
3198 VM_ceil, // #38 float(float v) ceil (QUAKE)
3199 NULL, // #39 (QUAKE)
3200 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3201 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3202 NULL, // #42 (QUAKE)
3203 VM_fabs, // #43 float(float f) fabs (QUAKE)
3204 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3205 VM_cvar, // #45 float(string s) cvar (QUAKE)
3206 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3207 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3208 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3209 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3210 NULL, // #50 (QUAKE)
3211 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3212 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3213 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3214 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3215 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3216 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3217 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3218 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3219 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3220 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3221 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3222 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3223 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3224 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3225 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3226 NULL, // #66 (QUAKE)
3227 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3228 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3229 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3230 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3231 NULL, // #71 (QUAKE)
3232 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3233 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3234 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3235 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3236 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3237 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3238 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3239 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3240 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3241 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3242 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3243 NULL, // #83 (QUAKE)
3244 NULL, // #84 (QUAKE)
3245 NULL, // #85 (QUAKE)
3246 NULL, // #86 (QUAKE)
3247 NULL, // #87 (QUAKE)
3248 NULL, // #88 (QUAKE)
3249 NULL, // #89 (QUAKE)
3250 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3251 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3252 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3253 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3254 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3255 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3256 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3257 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3258 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3259 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3260 // FrikaC and Telejano range #100-#199
3271 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3272 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3273 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3274 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3275 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3276 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3277 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3278 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3279 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3280 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3361 // FTEQW range #200-#299
3380 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3383 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3384 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3385 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3386 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3387 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3388 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3389 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3390 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3391 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3392 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3394 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3402 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3425 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.
3426 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
3427 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3428 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3429 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)
3430 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
3431 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)
3432 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)
3433 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)
3434 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)
3435 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)
3436 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
3437 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)
3438 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
3439 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.
3462 // CSQC range #300-#399
3463 NULL, // #300 void() clearscene (EXT_CSQC)
3464 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3465 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3466 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3467 NULL, // #304 void() renderscene (EXT_CSQC)
3468 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3469 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3470 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3471 NULL, // #308 void() R_EndPolygon
3473 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3474 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3478 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3479 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3480 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3481 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3482 NULL, // #319 void(string name) freepic (EXT_CSQC)
3483 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3484 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3485 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3486 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3487 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3488 NULL, // #325 void(void) drawresetcliparea
3493 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3494 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3495 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3496 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3497 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3498 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3499 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3500 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3501 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3502 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3503 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3504 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3505 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3506 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3507 NULL, // #344 vector() getmousepos (EXT_CSQC)
3508 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3509 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3510 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3511 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3512 NULL, // #349 float() isdemo (EXT_CSQC)
3513 VM_isserver, // #350 float() isserver (EXT_CSQC)
3514 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3515 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3516 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3517 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3523 NULL, // #360 float() readbyte (EXT_CSQC)
3524 NULL, // #361 float() readchar (EXT_CSQC)
3525 NULL, // #362 float() readshort (EXT_CSQC)
3526 NULL, // #363 float() readlong (EXT_CSQC)
3527 NULL, // #364 float() readcoord (EXT_CSQC)
3528 NULL, // #365 float() readangle (EXT_CSQC)
3529 NULL, // #366 string() readstring (EXT_CSQC)
3530 NULL, // #367 float() readfloat (EXT_CSQC)
3563 // LordHavoc's range #400-#499
3564 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3565 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3566 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3567 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3568 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3569 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3570 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3571 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3572 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)
3573 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3574 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3575 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3576 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3577 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3578 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3579 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3580 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3581 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3582 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3583 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3584 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3585 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3586 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3587 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3588 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3589 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3590 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3591 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3592 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3593 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3594 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3595 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3596 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3597 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3598 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3599 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3600 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3601 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3602 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3603 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3604 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3605 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3606 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3607 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3608 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3609 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3610 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3611 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3612 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3613 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3614 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3615 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3616 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3617 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3618 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3619 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3620 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3621 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3623 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3624 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3625 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3626 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3627 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3628 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3629 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3630 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3631 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3632 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3633 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3635 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3636 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3637 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3638 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3639 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3640 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3641 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3642 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3643 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3644 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3645 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3646 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3647 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3648 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3649 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3650 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3658 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3659 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3660 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3661 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3662 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3663 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3664 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3665 VM_SV_WritePicture, // #501
3667 VM_whichpack, // #503 string(string) whichpack = #503;
3674 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3675 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3676 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3677 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)
3678 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3679 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3680 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3681 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3682 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3683 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3693 VM_loadfromdata, // #529
3694 VM_loadfromfile, // #530
3695 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3697 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3698 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3704 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3705 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3706 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3769 VM_callfunction, // #605
3770 VM_writetofile, // #606
3771 VM_isfunction, // #607
3777 VM_parseentitydata, // #613
3788 VM_SV_getextresponse, // #624 string getextresponse(void)
3791 VM_sprintf, // #627 string sprintf(string format, ...)
3792 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3793 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3803 VM_digest_hex, // #639
3807 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3809 void SVVM_init_cmd(prvm_prog_t *prog)
3814 void SVVM_reset_cmd(prvm_prog_t *prog)
3816 World_End(&sv.world);
3817 if(PRVM_serverfunction(SV_Shutdown))
3819 func_t s = PRVM_serverfunction(SV_Shutdown);
3820 PRVM_serverglobalfloat(time) = sv.time;
3821 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3822 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");