6 //============================================================================
11 const char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
25 "DP_CSQC_ENTITYWORLDOBJECT "
26 "DP_CSQC_ENTITYMODELLIGHT "
27 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
29 "DP_CSQC_MINFPS_QUALITY "
30 "DP_CSQC_MULTIFRAME_INTERPOLATION "
31 "DP_CSQC_BOXPARTICLES "
32 "DP_CSQC_SPAWNPARTICLE "
33 "DP_CSQC_QUERYRENDERENTITY "
34 "DP_CSQC_ROTATEMOVES "
36 "DP_CSQC_V_CALCREFDEF_WIP1 "
37 "DP_CSQC_V_CALCREFDEF_WIP2 "
41 "DP_EF_DYNAMICMODELLIGHT "
50 "DP_EF_RESTARTANIM_BIT "
55 "DP_ENT_CUSTOMCOLORMAP "
56 "DP_ENT_EXTERIORMODELTOCLIENT "
59 "DP_ENT_LOWPRECISION "
61 "DP_ENT_TRAILEFFECTNUM "
63 "DP_GFX_EXTERNALTEXTURES "
64 "DP_GFX_EXTERNALTEXTURES_PERMAP "
66 "DP_GFX_MODEL_INTERPOLATION "
67 "DP_GFX_QUAKE3MODELTAGS "
71 "DP_GFX_FONTS_FREETYPE "
73 "DP_FONT_VARIABLEWIDTH "
75 "DP_HALFLIFE_MAP_CVAR "
78 "DP_LIGHTSTYLE_STATICVALUE "
82 "DP_MOVETYPEBOUNCEMISSILE "
83 "DP_MOVETYPEFLYWORLDONLY "
86 "DP_QC_ASINACOSATANATAN2TAN "
92 "DP_QC_CVAR_DEFSTRING "
93 "DP_QC_CVAR_DESCRIPTION "
97 "DP_QC_DIGEST_SHA256 "
100 "DP_QC_ENTITYSTRING "
102 "DP_QC_EXTRESPONSEPACKET "
104 "DP_QC_FINDCHAINFLAGS "
105 "DP_QC_FINDCHAINFLOAT "
106 "DP_QC_FINDCHAIN_TOFIELD "
112 "DP_QC_GETSURFACETRIANGLE "
113 "DP_QC_GETSURFACEPOINTATTRIBUTE "
115 "DP_QC_GETTAGINFO_BONEPROPERTIES "
117 "DP_QC_GETTIME_CDTRACK "
121 "DP_QC_MULTIPLETEMPSTRINGS "
122 "DP_QC_NUM_FOR_EDICT "
124 "DP_QC_SINCOSSQRTPOW "
127 "DP_QC_STRINGBUFFERS "
128 "DP_QC_STRINGBUFFERS_CVARLIST "
129 "DP_QC_STRINGBUFFERS_EXT_WIP "
130 "DP_QC_STRINGCOLORFUNCTIONS "
131 "DP_QC_STRING_CASE_FUNCTIONS "
133 "DP_QC_TOKENIZEBYSEPARATOR "
134 "DP_QC_TOKENIZE_CONSOLE "
137 "DP_QC_TRACE_MOVETYPE_HITMODEL "
138 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
139 "DP_QC_UNLIMITEDTEMPSTRINGS "
143 "DP_QC_VECTOANGLES_WITH_ROLL "
144 "DP_QC_VECTORVECTORS "
151 "DP_SKELETONOBJECTS "
152 "DP_SND_DIRECTIONLESSATTNNONE "
154 "DP_SND_SOUND7_WIP1 "
155 "DP_SND_SOUND7_WIP2 "
159 "DP_SND_GETSOUNDTIME "
161 "DP_VIDEO_SUBTITLES "
165 "DP_SV_BOUNCEFACTOR "
166 "DP_SV_CLIENTCAMERA "
167 "DP_SV_CLIENTCOLORS "
170 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
171 "DP_SV_DISABLECLIENTPREDICTION "
172 "DP_SV_DISCARDABLEDEMO "
173 "DP_SV_DRAWONLYTOCLIENT "
176 "DP_SV_ENTITYCONTENTSTRANSITION "
177 "DP_SV_MODELFLAGS_AS_EFFECTS "
178 "DP_SV_MOVETYPESTEP_LANDEVENT "
180 "DP_SV_NODRAWTOCLIENT "
181 "DP_SV_ONENTITYNOSPAWNFUNCTION "
182 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
184 "DP_SV_PING_PACKETLOSS "
185 "DP_SV_PLAYERPHYSICS "
187 "DP_SV_POINTPARTICLES "
189 "DP_SV_PRECACHEANYTIME "
193 "DP_SV_ROTATINGBMODEL "
197 "DP_SV_SPAWNFUNC_PREFIX "
198 "DP_SV_WRITEPICTURE "
199 "DP_SV_WRITEUNTERMINATEDSTRING "
203 "DP_TE_EXPLOSIONRGB "
205 "DP_TE_PARTICLECUBE "
206 "DP_TE_PARTICLERAIN "
207 "DP_TE_PARTICLESNOW "
209 "DP_TE_QUADEFFECTS1 "
212 "DP_TE_STANDARDEFFECTBUILTINS "
213 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
218 "FTE_CSQC_SKELETONOBJECTS "
221 "KRIMZON_SV_PARSECLIENTCOMMAND "
224 "NEXUIZ_PLAYERMODEL "
226 "PRYDON_CLIENTCURSOR "
227 "TENEBRAE_GFX_DLIGHTS "
232 //"EXT_CSQC " // not ready yet
239 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.
241 setorigin (entity, origin)
244 static void VM_SV_setorigin(prvm_prog_t *prog)
248 VM_SAFEPARMCOUNT(2, VM_setorigin);
250 e = PRVM_G_EDICT(OFS_PARM0);
251 if (e == prog->edicts)
253 VM_Warning(prog, "setorigin: can not modify world entity\n");
256 if (e->priv.server->free)
258 VM_Warning(prog, "setorigin: can not modify free entity\n");
261 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), PRVM_serveredictvector(e, origin));
262 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
263 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
267 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
268 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qboolean rotate)
272 for (i=0 ; i<3 ; i++)
274 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
276 // set derived values
277 VectorCopy (min, PRVM_serveredictvector(e, mins));
278 VectorCopy (max, PRVM_serveredictvector(e, maxs));
279 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
288 the size box is rotated by the current angle
289 LadyHavoc: no it isn't...
291 setsize (entity, minvector, maxvector)
294 static void VM_SV_setsize(prvm_prog_t *prog)
299 VM_SAFEPARMCOUNT(3, VM_setsize);
301 e = PRVM_G_EDICT(OFS_PARM0);
302 if (e == prog->edicts)
304 VM_Warning(prog, "setsize: can not modify world entity\n");
307 if (e->priv.server->free)
309 VM_Warning(prog, "setsize: can not modify free entity\n");
312 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), mins);
313 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), maxs);
314 SetMinMaxSize(prog, e, mins, maxs, false);
322 setmodel(entity, model)
325 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
326 static void VM_SV_setmodel(prvm_prog_t *prog)
332 VM_SAFEPARMCOUNT(2, VM_setmodel);
334 e = PRVM_G_EDICT(OFS_PARM0);
335 if (e == prog->edicts)
337 VM_Warning(prog, "setmodel: can not modify world entity\n");
340 if (e->priv.server->free)
342 VM_Warning(prog, "setmodel: can not modify free entity\n");
345 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
346 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
347 PRVM_serveredictfloat(e, modelindex) = i;
349 mod = SV_GetModelByIndex(i);
353 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
354 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
356 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
359 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
366 single print to a specific client
368 sprint(clientent, value)
371 static void VM_SV_sprint(prvm_prog_t *prog)
375 char string[VM_STRINGTEMP_LENGTH];
377 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
379 VM_VarString(prog, 1, string, sizeof(string));
381 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
382 // LadyHavoc: div0 requested that sprintto world operate like print
389 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
391 VM_Warning(prog, "tried to centerprint to a non-client\n");
395 client = svs.clients + entnum-1;
396 if (!client->netconnection)
399 MSG_WriteChar(&client->netconnection->message,svc_print);
400 MSG_WriteString(&client->netconnection->message, string);
408 single print to a specific client
410 centerprint(clientent, value)
413 static void VM_SV_centerprint(prvm_prog_t *prog)
417 char string[VM_STRINGTEMP_LENGTH];
419 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
421 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
423 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
425 VM_Warning(prog, "tried to centerprint to a non-client\n");
429 client = svs.clients + entnum-1;
430 if (!client->netconnection)
433 VM_VarString(prog, 1, string, sizeof(string));
434 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
435 MSG_WriteString(&client->netconnection->message, string);
442 particle(origin, color, count)
445 static void VM_SV_particle(prvm_prog_t *prog)
451 VM_SAFEPARMCOUNT(4, VM_SV_particle);
453 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
454 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
455 color = (int)PRVM_G_FLOAT(OFS_PARM2);
456 count = (int)PRVM_G_FLOAT(OFS_PARM3);
457 SV_StartParticle (org, dir, color, count);
467 static void VM_SV_ambientsound(prvm_prog_t *prog)
471 prvm_vec_t vol, attenuation;
474 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
476 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
477 samp = PRVM_G_STRING(OFS_PARM1);
478 vol = PRVM_G_FLOAT(OFS_PARM2);
479 attenuation = PRVM_G_FLOAT(OFS_PARM3);
481 // check to see if samp was properly precached
482 soundnum = SV_SoundIndex(samp, 1);
490 // add an svc_spawnambient command to the level signon packet
493 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
495 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
497 MSG_WriteVector(&sv.signon, pos, sv.protocol);
499 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
500 MSG_WriteShort (&sv.signon, soundnum);
502 MSG_WriteByte (&sv.signon, soundnum);
504 MSG_WriteByte (&sv.signon, (int)(vol*255));
505 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
513 Each entity can have eight independant sound sources, like voice,
516 Channel 0 is an auto-allocate channel, the others override anything
517 already running on that entity/channel pair.
519 An attenuation of 0 will play full volume everywhere in the level.
520 Larger attenuations will drop off.
524 static void VM_SV_sound(prvm_prog_t *prog)
528 prvm_edict_t *entity;
534 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
536 entity = PRVM_G_EDICT(OFS_PARM0);
537 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
538 sample = PRVM_G_STRING(OFS_PARM2);
539 nvolume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
542 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
546 attenuation = PRVM_G_FLOAT(OFS_PARM4);
550 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
555 if(channel >= 8 && channel <= 15) // weird QW feature
557 flags |= CHANNELFLAG_RELIABLE;
563 // LadyHavoc: we only let the qc set certain flags, others are off-limits
564 flags = (int)PRVM_G_FLOAT(OFS_PARM6) & (CHANNELFLAG_RELIABLE | CHANNELFLAG_FORCELOOP | CHANNELFLAG_PAUSED | CHANNELFLAG_FULLVOLUME);
567 if (nvolume < 0 || nvolume > 255)
569 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
573 if (attenuation < 0 || attenuation > 4)
575 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
579 channel = CHAN_USER2ENGINE(channel);
581 if (!IS_CHAN(channel))
583 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
587 SV_StartSound (entity, channel, sample, nvolume, attenuation, flags & CHANNELFLAG_RELIABLE, pitchchange);
594 Follows the same logic as VM_SV_sound, except instead of
595 an entity, an origin for the sound is provided, and channel
596 is omitted (since no entity is being tracked).
600 static void VM_SV_pointsound(prvm_prog_t *prog)
608 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
610 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
611 sample = PRVM_G_STRING(OFS_PARM1);
612 nvolume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
613 attenuation = PRVM_G_FLOAT(OFS_PARM3);
614 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
616 if (nvolume < 0 || nvolume > 255)
618 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
622 if (attenuation < 0 || attenuation > 4)
624 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
628 SV_StartPointSound (org, sample, nvolume, attenuation, pitchchange);
635 Used for use tracing and shot targeting
636 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
637 if the tryents flag is set.
639 traceline (vector1, vector2, movetype, ignore)
642 static void VM_SV_traceline(prvm_prog_t *prog)
649 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
651 prog->xfunction->builtinsprofile += 30;
653 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
654 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), v2);
655 move = (int)PRVM_G_FLOAT(OFS_PARM2);
656 ent = PRVM_G_EDICT(OFS_PARM3);
658 if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_IS_NAN(v2[2]))
659 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));
661 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtracelinelength.value);
663 VM_SetTraceGlobals(prog, &trace);
671 Used for use tracing and shot targeting
672 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
673 if the tryents flag is set.
675 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
678 // LadyHavoc: added this for my own use, VERY useful, similar to traceline
679 static void VM_SV_tracebox(prvm_prog_t *prog)
681 vec3_t v1, v2, m1, m2;
686 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
688 prog->xfunction->builtinsprofile += 30;
690 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
691 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), m1);
692 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), m2);
693 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), v2);
694 move = (int)PRVM_G_FLOAT(OFS_PARM4);
695 ent = PRVM_G_EDICT(OFS_PARM5);
697 if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_IS_NAN(v2[2]))
698 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));
700 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtraceboxlength.value);
702 VM_SetTraceGlobals(prog, &trace);
705 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
709 vec3_t move, end, tossentorigin, tossentmins, tossentmaxs;
710 vec3_t original_origin;
711 vec3_t original_velocity;
712 vec3_t original_angles;
713 vec3_t original_avelocity;
716 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
717 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
718 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
719 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
721 gravity = PRVM_serveredictfloat(tossent, gravity);
724 gravity *= sv_gravity.value * 0.025;
726 for (i = 0;i < 200;i++) // LadyHavoc: sanity check; never trace more than 10 seconds
728 SV_CheckVelocity (tossent);
729 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
730 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
731 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
732 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
733 VectorCopy(PRVM_serveredictvector(tossent, origin), tossentorigin);
734 VectorCopy(PRVM_serveredictvector(tossent, mins), tossentmins);
735 VectorCopy(PRVM_serveredictvector(tossent, maxs), tossentmaxs);
736 trace = SV_TraceBox(tossentorigin, tossentmins, tossentmaxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent), 0, 0, collision_extendmovelength.value);
737 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
738 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
740 if (trace.fraction < 1)
744 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
745 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
746 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
747 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
752 static void VM_SV_tracetoss(prvm_prog_t *prog)
756 prvm_edict_t *ignore;
758 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
760 prog->xfunction->builtinsprofile += 600;
762 ent = PRVM_G_EDICT(OFS_PARM0);
763 if (ent == prog->edicts)
765 VM_Warning(prog, "tracetoss: can not use world entity\n");
768 ignore = PRVM_G_EDICT(OFS_PARM1);
770 trace = SV_Trace_Toss(prog, ent, ignore);
772 VM_SetTraceGlobals(prog, &trace);
775 //============================================================================
777 static int checkpvsbytes;
778 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
780 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
786 // cycle to the next one
788 check = bound(1, check, svs.maxclients);
789 if (check == svs.maxclients)
797 prog->xfunction->builtinsprofile++;
799 if (i == svs.maxclients+1)
801 // look up the client's edict
802 ent = PRVM_EDICT_NUM(i);
803 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
804 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
806 // found a valid client (possibly the same one again)
810 // get the PVS for the entity
811 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
813 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
814 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
823 Returns a client (or object that has a client enemy) that would be a
826 If there is more than one valid option, they are cycled each frame
828 If (self.origin + self.viewofs) is not in the PVS of the current target,
829 it is not returned at all.
831 name checkclient ([ent])
834 int c_invis, c_notvis;
835 static void VM_SV_checkclient(prvm_prog_t *prog)
837 prvm_edict_t *ent, *self;
840 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_checkclient);
842 // find a new check if on a new frame
843 if (sv.time - sv.lastchecktime >= 0.1)
845 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
846 sv.lastchecktime = sv.time;
849 // return check if it might be visible
850 ent = PRVM_EDICT_NUM(sv.lastcheck);
851 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
853 VM_RETURN_EDICT(prog->edicts);
857 // if current entity can't possibly see the check entity, return 0
858 // optional entity parameter for self (EXT_ENTITYPARAM)
860 self = PRVM_G_EDICT(OFS_PARM0);
862 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
863 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
864 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
867 VM_RETURN_EDICT(prog->edicts);
871 // might be able to see it
873 VM_RETURN_EDICT(ent);
876 //============================================================================
882 Checks if an entity is in a point's PVS.
883 Should be fast but can be inexact.
885 float checkpvs(vector viewpos, entity viewee) = #240;
888 static void VM_SV_checkpvs(prvm_prog_t *prog)
890 vec3_t viewpos, absmin, absmax;
891 prvm_edict_t *viewee;
896 unsigned char fatpvs[MAX_MAP_LEAFS/8];
899 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
900 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
901 viewee = PRVM_G_EDICT(OFS_PARM1);
903 if(viewee->priv.server->free)
905 VM_Warning(prog, "checkpvs: can not check free entity\n");
906 PRVM_G_FLOAT(OFS_RETURN) = 4;
911 if(!sv.worldmodel || !sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
913 // no PVS support on this worldmodel... darn
914 PRVM_G_FLOAT(OFS_RETURN) = 3;
917 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
920 // viewpos isn't in any PVS... darn
921 PRVM_G_FLOAT(OFS_RETURN) = 2;
924 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
925 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
926 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, absmin, absmax);
928 // using fat PVS like FTEQW does (slow)
929 if(!sv.worldmodel || !sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
931 // no PVS support on this worldmodel... darn
932 PRVM_G_FLOAT(OFS_RETURN) = 3;
935 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
938 // viewpos isn't in any PVS... darn
939 PRVM_G_FLOAT(OFS_RETURN) = 2;
942 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
943 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
944 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, absmin, absmax);
953 Sends text over to the client's execution buffer
955 stuffcmd (clientent, value, ...)
958 static void VM_SV_stuffcmd(prvm_prog_t *prog)
962 char string[VM_STRINGTEMP_LENGTH];
964 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
966 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
967 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
969 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
973 VM_VarString(prog, 1, string, sizeof(string));
976 host_client = svs.clients + entnum-1;
977 Host_ClientCommands ("%s", string);
985 Returns a chain of entities that have origins within a spherical area
987 findradius (origin, radius)
990 static void VM_SV_findradius(prvm_prog_t *prog)
992 prvm_edict_t *ent, *chain;
993 vec_t radius, radius2;
994 vec3_t org, eorg, mins, maxs;
997 static prvm_edict_t *touchedicts[MAX_EDICTS];
1000 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
1003 chainfield = PRVM_G_INT(OFS_PARM2);
1005 chainfield = prog->fieldoffsets.chain;
1007 prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
1009 chain = (prvm_edict_t *)prog->edicts;
1011 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1012 radius = PRVM_G_FLOAT(OFS_PARM1);
1013 radius2 = radius * radius;
1015 mins[0] = org[0] - (radius + 1);
1016 mins[1] = org[1] - (radius + 1);
1017 mins[2] = org[2] - (radius + 1);
1018 maxs[0] = org[0] + (radius + 1);
1019 maxs[1] = org[1] + (radius + 1);
1020 maxs[2] = org[2] + (radius + 1);
1021 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1022 if (numtouchedicts > MAX_EDICTS)
1024 // this never happens
1025 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1026 numtouchedicts = MAX_EDICTS;
1028 for (i = 0;i < numtouchedicts;i++)
1030 ent = touchedicts[i];
1031 prog->xfunction->builtinsprofile++;
1032 // Quake did not return non-solid entities but darkplaces does
1033 // (note: this is the reason you can't blow up fallen zombies)
1034 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1036 // LadyHavoc: compare against bounding box rather than center so it
1037 // doesn't miss large objects, and use DotProduct instead of Length
1038 // for a major speedup
1039 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1040 if (sv_gameplayfix_findradiusdistancetobox.integer)
1042 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1043 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1044 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1047 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1048 if (DotProduct(eorg, eorg) < radius2)
1050 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1055 VM_RETURN_EDICT(chain);
1058 static void VM_SV_precache_sound(prvm_prog_t *prog)
1060 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1061 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1064 static void VM_SV_precache_model(prvm_prog_t *prog)
1066 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1067 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1068 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1075 float(float yaw, float dist[, settrace, ent]) walkmove
1078 static void VM_SV_walkmove(prvm_prog_t *prog)
1087 VM_SAFEPARMCOUNTRANGE(2, 4, VM_SV_walkmove);
1089 // assume failure if it returns early
1090 PRVM_G_FLOAT(OFS_RETURN) = 0;
1092 // optional entity parameter for self (EXT_ENTITYPARAM)
1093 if (prog->argc >= 4)
1094 ent = PRVM_G_EDICT(OFS_PARM3);
1096 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1097 if (ent == prog->edicts)
1099 VM_Warning(prog, "walkmove: can not modify world entity\n");
1102 if (ent->priv.server->free)
1104 VM_Warning(prog, "walkmove: can not modify free entity\n");
1107 yaw = PRVM_G_FLOAT(OFS_PARM0);
1108 dist = PRVM_G_FLOAT(OFS_PARM1);
1109 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1111 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1114 yaw = yaw*M_PI*2 / 360;
1116 move[0] = cos(yaw)*dist;
1117 move[1] = sin(yaw)*dist;
1120 // save program state, because SV_movestep may call other progs
1121 oldf = prog->xfunction;
1122 oldself = PRVM_serverglobaledict(self);
1124 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1127 // restore program state
1128 prog->xfunction = oldf;
1129 PRVM_serverglobaledict(self) = oldself;
1136 void([ent]) droptofloor
1140 static void VM_SV_droptofloor(prvm_prog_t *prog)
1143 vec3_t end, entorigin, entmins, entmaxs;
1146 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1148 // assume failure if it returns early
1149 PRVM_G_FLOAT(OFS_RETURN) = 0;
1151 // optional entity parameter for self (EXT_ENTITYPARAM)
1152 if (prog->argc >= 1)
1153 ent = PRVM_G_EDICT(OFS_PARM0);
1155 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1156 if (ent == prog->edicts)
1158 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1161 if (ent->priv.server->free)
1163 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1167 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1170 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1171 SV_NudgeOutOfSolid(ent);
1173 VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
1174 VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
1175 VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
1176 trace = SV_TraceBox(entorigin, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
1177 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1180 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]);
1181 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1182 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
1183 VectorSubtract(trace.endpos, offset, trace.endpos);
1184 if (trace.startsolid)
1186 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]);
1188 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1189 PRVM_serveredictedict(ent, groundentity) = 0;
1190 PRVM_G_FLOAT(OFS_RETURN) = 1;
1192 else if (trace.fraction < 1)
1194 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]);
1195 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1196 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1197 SV_NudgeOutOfSolid(ent);
1199 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1200 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1201 PRVM_G_FLOAT(OFS_RETURN) = 1;
1202 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1203 ent->priv.server->suspendedinairflag = true;
1208 if (!trace.allsolid && trace.fraction < 1)
1210 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1212 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1213 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1214 PRVM_G_FLOAT(OFS_RETURN) = 1;
1215 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1216 ent->priv.server->suspendedinairflag = true;
1225 void(float style, string value) lightstyle
1228 static void VM_SV_lightstyle(prvm_prog_t *prog)
1235 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1237 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1238 val = PRVM_G_STRING(OFS_PARM1);
1240 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1241 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1244 // change the string in sv
1245 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1247 // send message to all clients on this server
1248 if (sv.state != ss_active)
1251 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1253 if (client->active && client->netconnection)
1255 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1256 MSG_WriteChar (&client->netconnection->message,style);
1257 MSG_WriteString (&client->netconnection->message, val);
1267 static void VM_SV_checkbottom(prvm_prog_t *prog)
1269 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1270 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1278 static void VM_SV_pointcontents(prvm_prog_t *prog)
1281 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1282 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point);
1283 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(SV_PointSuperContents(point));
1290 Pick a vector for the player to shoot along
1291 vector aim(entity, missilespeed)
1294 static void VM_SV_aim(prvm_prog_t *prog)
1296 prvm_edict_t *ent, *check, *bestent;
1297 vec3_t start, dir, end, bestdir;
1300 float dist, bestdist;
1303 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1305 // assume failure if it returns early
1306 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1307 // if sv_aim is so high it can't possibly accept anything, skip out early
1308 if (sv_aim.value >= 1)
1311 ent = PRVM_G_EDICT(OFS_PARM0);
1312 if (ent == prog->edicts)
1314 VM_Warning(prog, "aim: can not use world entity\n");
1317 if (ent->priv.server->free)
1319 VM_Warning(prog, "aim: can not use free entity\n");
1322 //speed = PRVM_G_FLOAT(OFS_PARM1);
1324 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1327 // try sending a trace straight
1328 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1329 VectorMA (start, 2048, dir, end);
1330 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1331 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1332 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1334 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1339 // try all possible entities
1340 VectorCopy (dir, bestdir);
1341 bestdist = sv_aim.value;
1344 check = PRVM_NEXT_EDICT(prog->edicts);
1345 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1347 prog->xfunction->builtinsprofile++;
1348 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1352 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1353 continue; // don't aim at teammate
1354 for (j=0 ; j<3 ; j++)
1355 end[j] = PRVM_serveredictvector(check, origin)[j]
1356 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1357 VectorSubtract (end, start, dir);
1358 VectorNormalize (dir);
1359 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1360 if (dist < bestdist)
1361 continue; // to far to turn
1362 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1363 if (tr.ent == check)
1364 { // can shoot at this one
1372 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1373 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1374 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1376 VectorNormalize (end);
1377 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1381 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1386 ===============================================================================
1390 ===============================================================================
1393 #define MSG_BROADCAST 0 // unreliable to all
1394 #define MSG_ONE 1 // reliable to one (msg_entity)
1395 #define MSG_ALL 2 // reliable to all
1396 #define MSG_INIT 3 // write to the init string
1397 #define MSG_ENTITY 5
1399 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1405 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1409 return &sv.datagram;
1412 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1413 entnum = PRVM_NUM_FOR_EDICT(ent);
1414 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1416 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1417 return &sv.reliable_datagram;
1420 return &svs.clients[entnum-1].netconnection->message;
1423 VM_Warning(prog, "WriteDest: bad destination\n");
1425 return &sv.reliable_datagram;
1431 return sv.writeentitiestoclient_msg;
1437 static void VM_SV_WriteByte(prvm_prog_t *prog)
1439 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1440 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1443 static void VM_SV_WriteChar(prvm_prog_t *prog)
1445 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1446 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1449 static void VM_SV_WriteShort(prvm_prog_t *prog)
1451 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1452 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1455 static void VM_SV_WriteLong(prvm_prog_t *prog)
1457 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1458 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1461 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1463 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1464 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1467 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1469 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1470 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1473 static void VM_SV_WriteString(prvm_prog_t *prog)
1475 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1476 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1479 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1481 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1482 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1486 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1488 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1489 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1492 // writes a picture as at most size bytes of data
1494 // IMGNAME \0 SIZE(short) IMGDATA
1495 // if failed to read/compress:
1497 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1498 static void VM_SV_WritePicture(prvm_prog_t *prog)
1500 const char *imgname;
1504 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1506 imgname = PRVM_G_STRING(OFS_PARM1);
1507 size = (size_t) PRVM_G_FLOAT(OFS_PARM2);
1511 MSG_WriteString(WriteDest(prog), imgname);
1512 if(Image_Compress(imgname, size, &buf, &size))
1515 MSG_WriteShort(WriteDest(prog), (int)size);
1516 SZ_Write(WriteDest(prog), (unsigned char *) buf, (int)size);
1521 MSG_WriteShort(WriteDest(prog), 0);
1525 //////////////////////////////////////////////////////////
1527 static void VM_SV_makestatic(prvm_prog_t *prog)
1532 // allow 0 parameters due to an id1 qc bug in which this function is used
1533 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1534 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1536 if (prog->argc >= 1)
1537 ent = PRVM_G_EDICT(OFS_PARM0);
1539 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1540 if (ent == prog->edicts)
1542 VM_Warning(prog, "makestatic: can not modify world entity\n");
1545 if (ent->priv.server->free)
1547 VM_Warning(prog, "makestatic: can not modify free entity\n");
1552 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1557 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1558 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1559 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1561 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1563 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1564 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1565 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1569 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1570 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1571 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1574 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1575 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1576 for (i=0 ; i<3 ; i++)
1578 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1579 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1582 // throw the entity away now
1583 PRVM_ED_Free(prog, ent);
1586 //=============================================================================
1593 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1599 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1601 ent = PRVM_G_EDICT(OFS_PARM0);
1602 i = PRVM_NUM_FOR_EDICT(ent);
1603 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1605 Con_Print("tried to setspawnparms on a non-client\n");
1609 // copy spawn parms out of the client_t
1610 client = svs.clients + i-1;
1611 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1612 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1619 Returns a color vector indicating the lighting at the requested point.
1621 (Internal Operation note: actually measures the light beneath the point, just like
1622 the model lighting on the client)
1627 static void VM_SV_getlight(prvm_prog_t *prog)
1629 vec3_t ambientcolor, diffusecolor, diffusenormal;
1631 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1632 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
1633 VectorClear(ambientcolor);
1634 VectorClear(diffusecolor);
1635 VectorClear(diffusenormal);
1636 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1637 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1638 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1643 unsigned char type; // 1/2/8 or 0 to indicate unused
1647 static customstat_t vm_customstats[MAX_CL_STATS]; // matches the regular stat numbers, but only MIN_VM_STAT to MAX_VM_STAT range is used if things are working properly (can register stats from MAX_VM_STAT to MAX_CL_STATS but will warn)
1648 static int vm_customstats_last;
1650 void VM_CustomStats_Clear (void)
1652 memset(vm_customstats, 0, sizeof(vm_customstats));
1653 vm_customstats_last = -1;
1656 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1658 prvm_prog_t *prog = SVVM_prog;
1666 for(i=MIN_VM_STAT; i<=vm_customstats_last ;i++)
1668 if(!vm_customstats[i].type)
1670 switch(vm_customstats[i].type)
1672 //string as 16 bytes
1675 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1676 stats[i] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1677 stats[i+1] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1678 stats[i+2] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1679 stats[i+3] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1681 //float field sent as-is
1683 // can't directly use PRVM_E_INT on the field because it may be PRVM_64 and a double is not the representation we want to send
1684 u.f = PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1687 //integer value of float field
1689 stats[i] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1697 // void(float index, float type, .void field) SV_AddStat = #232;
1698 // Set up an auto-sent player stat.
1699 // Client's get thier own fields sent to them. Index may not be less than 32.
1700 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1701 // 1: string (4 stats carrying a total of 16 charactures)
1702 // 2: float (one stat, float converted to an integer for transportation)
1703 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1704 static void VM_SV_AddStat(prvm_prog_t *prog)
1708 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1710 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1711 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1712 off = PRVM_G_INT (OFS_PARM2);
1721 VM_Warning(prog, "PF_SV_AddStat: unrecognized type %i - supported types are 1 (string up to 16 bytes, takes 4 stat slots), 2 (truncate to int32), 8 (send as float)", type);
1727 VM_Warning(prog, "PF_SV_AddStat: index (%i) may not be less than %i\n", i, MIN_VM_STAT);
1731 if (i >= MAX_CL_STATS)
1733 VM_Warning(prog, "PF_SV_AddStat: index (%i) >= MAX_CL_STATS (%i), not supported by protocol, and AddStat beyond MAX_VM_STAT (%i) conflicts with engine MOVEVARS\n", i, MAX_CL_STATS, MAX_VM_STAT);
1737 if (i > (MAX_CL_STATS - 4) && type == 1)
1739 VM_Warning(prog, "PF_SV_AddStat: index (%i) > (MAX_CL_STATS (%i) - 4) with string type won't fit in the protocol, and AddStat beyond MAX_VM_STAT conflicts with engine MOVEVARS\n", i, MAX_CL_STATS);
1743 // these are hazardous to override but sort of allowed if one wants to be adventurous... and enjoys warnings.
1744 if (i < MIN_VM_STAT)
1745 VM_Warning(prog, "PF_SV_AddStat: index (%i) < MIN_VM_STAT (%i) may conflict with engine stats - allowed, but this may break things\n", i, MIN_VM_STAT);
1746 else if (i >= MAX_VM_STAT)
1747 VM_Warning(prog, "PF_SV_AddStat: index (%i) >= MAX_VM_STAT (%i) conflicts with engine stats - allowed, but this may break slowmo and stuff\n", i, MAX_VM_STAT);
1748 else if (i > (MAX_VM_STAT - 4) && type == 1)
1749 VM_Warning(prog, "PF_SV_AddStat: index (%i) >= MAX_VM_STAT (%i) - 4 with string type won't fit within MAX_VM_STAT, thus conflicting with engine stats - allowed, but this may break slowmo and stuff\n", i, MAX_VM_STAT);
1751 vm_customstats[i].type = type;
1752 vm_customstats[i].fieldoffset = off;
1753 if(vm_customstats_last < i)
1754 vm_customstats_last = i;
1761 copies data from one entity to another
1763 copyentity(src, dst)
1766 static void VM_SV_copyentity(prvm_prog_t *prog)
1768 prvm_edict_t *in, *out;
1769 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1770 in = PRVM_G_EDICT(OFS_PARM0);
1771 if (in == prog->edicts)
1773 VM_Warning(prog, "copyentity: can not read world entity\n");
1776 if (in->priv.server->free)
1778 VM_Warning(prog, "copyentity: can not read free entity\n");
1781 out = PRVM_G_EDICT(OFS_PARM1);
1782 if (out == prog->edicts)
1784 VM_Warning(prog, "copyentity: can not modify world entity\n");
1787 if (out->priv.server->free)
1789 VM_Warning(prog, "copyentity: can not modify free entity\n");
1792 memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
1793 if (VectorCompare(PRVM_serveredictvector(out, absmin), PRVM_serveredictvector(out, absmax)))
1803 sets the color of a client and broadcasts the update to all connected clients
1805 setcolor(clientent, value)
1808 static void VM_SV_setcolor(prvm_prog_t *prog)
1813 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1814 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1815 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1817 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1819 Con_Print("tried to setcolor a non-client\n");
1823 client = svs.clients + entnum-1;
1826 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1827 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1830 if (client->old_colors != client->colors)
1832 client->old_colors = client->colors;
1833 // send notification to all clients
1834 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1835 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1836 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1844 effect(origin, modelname, startframe, framecount, framerate)
1847 static void VM_SV_effect(prvm_prog_t *prog)
1852 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1853 s = PRVM_G_STRING(OFS_PARM1);
1856 VM_Warning(prog, "effect: no model specified\n");
1860 i = SV_ModelIndex(s, 1);
1863 VM_Warning(prog, "effect: model not precached\n");
1867 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1869 VM_Warning(prog, "effect: framecount < 1\n");
1873 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1875 VM_Warning(prog, "effect: framerate < 1\n");
1879 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1880 SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1883 static void VM_SV_te_blood(prvm_prog_t *prog)
1885 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1886 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1888 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1889 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1891 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1892 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1893 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1895 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1896 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1897 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1899 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1900 SV_FlushBroadcastMessages();
1903 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1905 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1906 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1908 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1909 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1911 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1912 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1913 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1915 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1916 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1917 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1919 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1921 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1922 SV_FlushBroadcastMessages();
1925 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1927 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1928 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1929 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1935 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1936 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1937 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1938 SV_FlushBroadcastMessages();
1941 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1943 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1944 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1946 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1947 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1949 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1950 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1953 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1954 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1955 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1961 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1963 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1964 // gravity true/false
1965 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1968 SV_FlushBroadcastMessages();
1971 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1973 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1974 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1976 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1977 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1979 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1980 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1983 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1984 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1985 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1989 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1991 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1993 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1994 SV_FlushBroadcastMessages();
1997 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1999 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
2000 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2002 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2003 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2005 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2006 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2007 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2009 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2010 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2011 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2014 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2015 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2017 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2019 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2020 SV_FlushBroadcastMessages();
2023 static void VM_SV_te_spark(prvm_prog_t *prog)
2025 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
2026 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2028 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2029 MSG_WriteByte(&sv.datagram, TE_SPARK);
2031 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2032 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2033 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2035 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2036 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2037 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2039 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2040 SV_FlushBroadcastMessages();
2043 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2045 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2046 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2047 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2049 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2050 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2052 SV_FlushBroadcastMessages();
2055 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2057 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2058 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2059 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2061 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2062 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2063 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2064 SV_FlushBroadcastMessages();
2067 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2069 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2070 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2071 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2074 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2075 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2076 SV_FlushBroadcastMessages();
2079 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2081 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2082 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2083 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
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_smallflash(prvm_prog_t *prog)
2093 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2094 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2095 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
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_customflash(prvm_prog_t *prog)
2105 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2106 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2108 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2109 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2111 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2112 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2113 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2115 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2117 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2119 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2120 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2121 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2122 SV_FlushBroadcastMessages();
2125 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2127 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2128 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2129 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2131 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2132 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2133 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2134 SV_FlushBroadcastMessages();
2137 static void VM_SV_te_spike(prvm_prog_t *prog)
2139 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2140 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2141 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2143 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2144 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2145 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2146 SV_FlushBroadcastMessages();
2149 static void VM_SV_te_superspike(prvm_prog_t *prog)
2151 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2152 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2153 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2155 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2156 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2157 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2158 SV_FlushBroadcastMessages();
2161 static void VM_SV_te_explosion(prvm_prog_t *prog)
2163 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2164 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2165 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2167 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2168 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2169 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2170 SV_FlushBroadcastMessages();
2173 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2175 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2176 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2177 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2179 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2180 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2181 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2182 SV_FlushBroadcastMessages();
2185 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2187 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2188 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2189 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2191 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2192 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2193 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2194 SV_FlushBroadcastMessages();
2197 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2199 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2200 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2201 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2203 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2204 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2205 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2206 SV_FlushBroadcastMessages();
2209 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2211 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2212 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2213 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2215 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2216 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2217 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2218 SV_FlushBroadcastMessages();
2221 static void VM_SV_te_teleport(prvm_prog_t *prog)
2223 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2224 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2225 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2227 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2230 SV_FlushBroadcastMessages();
2233 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2235 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2236 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2237 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2239 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2240 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2241 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2243 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2244 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2245 SV_FlushBroadcastMessages();
2248 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2250 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2251 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2252 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2254 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2256 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2257 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2258 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2260 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2261 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2262 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2263 SV_FlushBroadcastMessages();
2266 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2268 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2269 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2270 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2272 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2274 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2275 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2276 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2278 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2279 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2280 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2281 SV_FlushBroadcastMessages();
2284 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2286 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2287 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2288 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2290 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2292 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2293 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2294 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2296 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2297 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2298 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2299 SV_FlushBroadcastMessages();
2302 static void VM_SV_te_beam(prvm_prog_t *prog)
2304 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2305 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2306 MSG_WriteByte(&sv.datagram, TE_BEAM);
2308 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2310 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2311 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2312 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2314 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2315 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2316 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2317 SV_FlushBroadcastMessages();
2320 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2322 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2323 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2324 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2325 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2326 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2327 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2328 SV_FlushBroadcastMessages();
2331 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2333 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2334 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2335 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2337 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2338 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2339 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2341 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2342 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2343 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2345 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2346 SV_FlushBroadcastMessages();
2349 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2350 //this function originally written by KrimZon, made shorter by LadyHavoc
2351 static void VM_SV_clientcommand(prvm_prog_t *prog)
2353 client_t *temp_client;
2355 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2357 //find client for this entity
2358 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2359 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2361 Con_Print("PF_clientcommand: entity is not a client\n");
2365 temp_client = host_client;
2366 host_client = svs.clients + i;
2367 Cmd_ExecuteString(&cmd_serverfromclient, PRVM_G_STRING(OFS_PARM1), src_client, true);
2368 host_client = temp_client;
2371 //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)
2372 static void VM_SV_setattachment(prvm_prog_t *prog)
2374 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2375 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2376 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2379 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2381 if (e == prog->edicts)
2383 VM_Warning(prog, "setattachment: can not modify world entity\n");
2386 if (e->priv.server->free)
2388 VM_Warning(prog, "setattachment: can not modify free entity\n");
2392 if (tagentity == NULL)
2393 tagentity = prog->edicts;
2397 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2399 model = SV_GetModelFromEdict(tagentity);
2402 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2404 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);
2407 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));
2410 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2411 PRVM_serveredictfloat(e, tag_index) = tagindex;
2414 /////////////////////////////////////////
2415 // DP_MD3_TAGINFO extension coded by VorteX
2417 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2421 i = (int)PRVM_serveredictfloat(e, modelindex);
2422 if (i < 1 || i >= MAX_MODELS)
2425 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2428 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2435 Matrix4x4_CreateIdentity(tag_localmatrix);
2437 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2439 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2450 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2453 float pitchsign = 1;
2455 scale = PRVM_serveredictfloat(ent, scale);
2460 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);
2463 pitchsign = SV_GetPitchSign(prog, ent);
2464 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);
2468 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2471 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2473 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2474 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2475 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2476 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2478 *out = identitymatrix;
2482 // Warnings/errors code:
2483 // 0 - normal (everything all-right)
2486 // 3 - null or non-precached model
2487 // 4 - no tags with requested index
2488 // 5 - runaway loop at attachment chain
2489 extern cvar_t cl_bob;
2490 extern cvar_t cl_bobcycle;
2491 extern cvar_t cl_bobup;
2492 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2495 int modelindex, attachloop;
2496 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2499 *out = identitymatrix; // warnings and errors return identical matrix
2501 if (ent == prog->edicts)
2503 if (ent->priv.server->free)
2506 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2507 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2510 model = SV_GetModelByIndex(modelindex);
2512 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2513 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2514 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2516 tagmatrix = identitymatrix;
2517 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2521 if (attachloop >= 256) // prevent runaway looping
2523 // apply transformation by child's tagindex on parent entity and then
2524 // by parent entity itself
2525 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2526 if (ret && attachloop == 0)
2528 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2529 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2530 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2531 // next iteration we process the parent entity
2532 if (PRVM_serveredictedict(ent, tag_entity))
2534 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2535 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2542 // RENDER_VIEWMODEL magic
2543 if (PRVM_serveredictedict(ent, viewmodelforclient))
2545 Matrix4x4_Copy(&tagmatrix, out);
2546 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2548 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2549 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2552 // Cl_bob, ported from rendering code
2553 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2556 // LadyHavoc: this code is *weird*, but not replacable (I think it
2557 // should be done in QC on the server, but oh well, quake is quake)
2558 // LadyHavoc: figured out bobup: the time at which the sin is at 180
2559 // degrees (which allows lengthening or squishing the peak or valley)
2560 cycle = sv.time/cl_bobcycle.value;
2561 cycle -= (int)cycle;
2562 if (cycle < cl_bobup.value)
2563 cycle = sin(M_PI * cycle / cl_bobup.value);
2565 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2566 // bob is proportional to velocity in the xy plane
2567 // (don't count Z, or jumping messes it up)
2568 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;
2569 bob = bob*0.3 + bob*0.7*cycle;
2570 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2577 //float(entity ent, string tagname) gettagindex;
2579 static void VM_SV_gettagindex(prvm_prog_t *prog)
2582 const char *tag_name;
2585 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2587 ent = PRVM_G_EDICT(OFS_PARM0);
2588 tag_name = PRVM_G_STRING(OFS_PARM1);
2590 if (ent == prog->edicts)
2592 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2595 if (ent->priv.server->free)
2597 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2602 if (!SV_GetModelFromEdict(ent))
2603 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2606 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2608 if(developer_extra.integer)
2609 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2611 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2614 //vector(entity ent, float tagindex) gettaginfo;
2615 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2619 matrix4x4_t tag_matrix;
2620 matrix4x4_t tag_localmatrix;
2622 const char *tagname;
2624 vec3_t forward, left, up, origin;
2625 const dp_model_t *model;
2627 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2629 e = PRVM_G_EDICT(OFS_PARM0);
2630 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2632 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2633 Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
2634 VectorCopy(forward, PRVM_serverglobalvector(v_forward));
2635 VectorNegate(left, PRVM_serverglobalvector(v_right));
2636 VectorCopy(up, PRVM_serverglobalvector(v_up));
2637 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2638 model = SV_GetModelFromEdict(e);
2639 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2640 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2641 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2642 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2643 Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
2645 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2646 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2647 VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
2648 VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
2649 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2650 VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset));
2655 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2658 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2661 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2664 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2667 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2672 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2673 static void VM_SV_dropclient(prvm_prog_t *prog)
2676 client_t *oldhostclient;
2677 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2678 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2679 if (clientnum < 0 || clientnum >= svs.maxclients)
2681 VM_Warning(prog, "dropclient: not a client\n");
2684 if (!svs.clients[clientnum].active)
2686 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2689 oldhostclient = host_client;
2690 host_client = svs.clients + clientnum;
2691 SV_DropClient(false);
2692 host_client = oldhostclient;
2695 //entity() spawnclient (DP_SV_BOTCLIENT)
2696 static void VM_SV_spawnclient(prvm_prog_t *prog)
2700 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2701 prog->xfunction->builtinsprofile += 2;
2703 for (i = 0;i < svs.maxclients;i++)
2705 if (!svs.clients[i].active)
2707 prog->xfunction->builtinsprofile += 100;
2708 SV_ConnectClient (i, NULL);
2709 // this has to be set or else ClientDisconnect won't be called
2710 // we assume the qc will call ClientConnect...
2711 svs.clients[i].clientconnectcalled = true;
2712 ed = PRVM_EDICT_NUM(i + 1);
2716 VM_RETURN_EDICT(ed);
2719 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2720 static void VM_SV_clienttype(prvm_prog_t *prog)
2723 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2724 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2725 if (clientnum < 0 || clientnum >= svs.maxclients)
2726 PRVM_G_FLOAT(OFS_RETURN) = 3;
2727 else if (!svs.clients[clientnum].active)
2728 PRVM_G_FLOAT(OFS_RETURN) = 0;
2729 else if (svs.clients[clientnum].netconnection)
2730 PRVM_G_FLOAT(OFS_RETURN) = 1;
2732 PRVM_G_FLOAT(OFS_RETURN) = 2;
2739 string(string key) serverkey
2742 static void VM_SV_serverkey(prvm_prog_t *prog)
2744 char string[VM_STRINGTEMP_LENGTH];
2745 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2746 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2747 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2750 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2751 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2756 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2758 e = PRVM_G_EDICT(OFS_PARM0);
2759 if (e == prog->edicts)
2761 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2764 if (e->priv.server->free)
2766 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2769 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2770 if (i <= 0 || i >= MAX_MODELS)
2772 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2775 if (!sv.model_precache[i][0])
2777 VM_Warning(prog, "setmodelindex: model not precached\n");
2781 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2782 PRVM_serveredictfloat(e, modelindex) = i;
2784 mod = SV_GetModelByIndex(i);
2788 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2789 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2791 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2794 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2797 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2798 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2801 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2803 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2805 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2806 if (i <= 0 || i >= MAX_MODELS)
2808 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2811 if (!sv.model_precache[i][0])
2813 VM_Warning(prog, "modelnameforindex: model not precached\n");
2817 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2820 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2821 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2824 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2825 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2828 PRVM_G_FLOAT(OFS_RETURN) = i;
2831 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2832 static void VM_SV_trailparticles(prvm_prog_t *prog)
2835 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2837 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2840 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2841 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2842 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2843 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start);
2844 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end);
2845 MSG_WriteVector(&sv.datagram, start, sv.protocol);
2846 MSG_WriteVector(&sv.datagram, end, sv.protocol);
2847 SV_FlushBroadcastMessages();
2850 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2851 static void VM_SV_pointparticles(prvm_prog_t *prog)
2853 int effectnum, count;
2855 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2857 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2860 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2861 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2862 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2863 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2864 if (count == 1 && !VectorLength2(vel))
2867 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2868 MSG_WriteShort(&sv.datagram, effectnum);
2869 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2873 // 1+2+12+12+2=29 bytes
2874 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2875 MSG_WriteShort(&sv.datagram, effectnum);
2876 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2877 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2878 MSG_WriteShort(&sv.datagram, count);
2881 SV_FlushBroadcastMessages();
2884 //PF_setpause, // void(float pause) setpause = #531;
2885 static void VM_SV_setpause(prvm_prog_t *prog) {
2887 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2888 if (pauseValue != 0) { //pause the game
2890 sv.pausedstart = realtime;
2891 } else { //disable pause, in case it was enabled
2892 if (sv.paused != 0) {
2897 // send notification to all clients
2898 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2899 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2902 // #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.
2903 static void VM_SV_skel_create(prvm_prog_t *prog)
2905 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2906 dp_model_t *model = SV_GetModelByIndex(modelindex);
2907 skeleton_t *skeleton;
2909 PRVM_G_FLOAT(OFS_RETURN) = 0;
2910 if (!model || !model->num_bones)
2912 for (i = 0;i < MAX_EDICTS;i++)
2913 if (!prog->skeletons[i])
2915 if (i == MAX_EDICTS)
2917 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(prog->progs_mempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2918 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2919 skeleton->model = model;
2920 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2921 // initialize to identity matrices
2922 for (i = 0;i < skeleton->model->num_bones;i++)
2923 skeleton->relativetransforms[i] = identitymatrix;
2926 // #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
2927 static void VM_SV_skel_build(prvm_prog_t *prog)
2929 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2930 skeleton_t *skeleton;
2931 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2932 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2933 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2934 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2935 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2936 dp_model_t *model = SV_GetModelByIndex(modelindex);
2940 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2941 frameblend_t frameblend[MAX_FRAMEBLENDS];
2942 matrix4x4_t bonematrix;
2944 PRVM_G_FLOAT(OFS_RETURN) = 0;
2945 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2947 firstbone = max(0, firstbone);
2948 lastbone = min(lastbone, model->num_bones - 1);
2949 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2950 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2951 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time);
2952 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2954 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2956 memset(&bonematrix, 0, sizeof(bonematrix));
2957 for (blendindex = 0;blendindex < numblends;blendindex++)
2959 Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2960 Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp);
2962 Matrix4x4_Normalize3(&bonematrix, &bonematrix);
2963 Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac);
2965 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2968 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2969 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
2971 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2972 skeleton_t *skeleton;
2973 PRVM_G_FLOAT(OFS_RETURN) = 0;
2974 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2976 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2979 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2980 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
2982 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2983 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2984 skeleton_t *skeleton;
2985 PRVM_G_INT(OFS_RETURN) = 0;
2986 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2988 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2990 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
2993 // #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)
2994 static void VM_SV_skel_get_boneparent(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;
2999 PRVM_G_FLOAT(OFS_RETURN) = 0;
3000 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3002 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3004 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
3007 // #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
3008 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
3010 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3011 const char *tagname = PRVM_G_STRING(OFS_PARM1);
3012 skeleton_t *skeleton;
3013 PRVM_G_FLOAT(OFS_RETURN) = 0;
3014 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3016 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
3019 // #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)
3020 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
3022 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3023 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3024 skeleton_t *skeleton;
3026 vec3_t forward, left, up, origin;
3027 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3028 VectorClear(PRVM_clientglobalvector(v_forward));
3029 VectorClear(PRVM_clientglobalvector(v_right));
3030 VectorClear(PRVM_clientglobalvector(v_up));
3031 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3033 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3035 matrix = skeleton->relativetransforms[bonenum];
3036 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3037 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3038 VectorNegate(left, PRVM_clientglobalvector(v_right));
3039 VectorCopy(up, PRVM_clientglobalvector(v_up));
3040 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3043 // #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)
3044 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
3046 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3047 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3048 skeleton_t *skeleton;
3051 vec3_t forward, left, up, origin;
3052 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3053 VectorClear(PRVM_clientglobalvector(v_forward));
3054 VectorClear(PRVM_clientglobalvector(v_right));
3055 VectorClear(PRVM_clientglobalvector(v_up));
3056 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3058 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3060 matrix = skeleton->relativetransforms[bonenum];
3061 // convert to absolute
3062 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3065 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3067 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3068 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3069 VectorNegate(left, PRVM_clientglobalvector(v_right));
3070 VectorCopy(up, PRVM_clientglobalvector(v_up));
3071 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3074 // #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)
3075 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3077 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3078 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3079 vec3_t forward, left, up, origin;
3080 skeleton_t *skeleton;
3082 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3084 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3086 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3087 VectorNegate(PRVM_clientglobalvector(v_right), left);
3088 VectorCopy(PRVM_clientglobalvector(v_up), up);
3089 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3090 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3091 skeleton->relativetransforms[bonenum] = matrix;
3094 // #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)
3095 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3097 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3098 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3099 vec3_t forward, left, up, origin;
3100 skeleton_t *skeleton;
3103 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3105 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3107 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3108 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3109 VectorNegate(PRVM_clientglobalvector(v_right), left);
3110 VectorCopy(PRVM_clientglobalvector(v_up), up);
3111 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3112 temp = skeleton->relativetransforms[bonenum];
3113 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3116 // #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)
3117 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3119 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3120 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3121 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3123 vec3_t forward, left, up, origin;
3124 skeleton_t *skeleton;
3127 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3129 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3130 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3131 VectorNegate(PRVM_clientglobalvector(v_right), left);
3132 VectorCopy(PRVM_clientglobalvector(v_up), up);
3133 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3134 firstbone = max(0, firstbone);
3135 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3136 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3138 temp = skeleton->relativetransforms[bonenum];
3139 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3143 // #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
3144 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3146 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3147 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3148 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3149 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3151 skeleton_t *skeletondst;
3152 skeleton_t *skeletonsrc;
3153 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3155 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3157 firstbone = max(0, firstbone);
3158 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3159 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3160 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3161 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3164 // #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)
3165 static void VM_SV_skel_delete(prvm_prog_t *prog)
3167 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3168 skeleton_t *skeleton;
3169 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3172 prog->skeletons[skeletonindex] = NULL;
3175 // #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
3176 static void VM_SV_frameforname(prvm_prog_t *prog)
3178 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3179 dp_model_t *model = SV_GetModelByIndex(modelindex);
3180 const char *name = PRVM_G_STRING(OFS_PARM1);
3182 PRVM_G_FLOAT(OFS_RETURN) = -1;
3183 if (!model || !model->animscenes)
3185 for (i = 0;i < model->numframes;i++)
3187 if (!strcasecmp(model->animscenes[i].name, name))
3189 PRVM_G_FLOAT(OFS_RETURN) = i;
3195 // #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.
3196 static void VM_SV_frameduration(prvm_prog_t *prog)
3198 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3199 dp_model_t *model = SV_GetModelByIndex(modelindex);
3200 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3201 PRVM_G_FLOAT(OFS_RETURN) = 0;
3202 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3204 if (model->animscenes[framenum].framerate)
3205 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3209 prvm_builtin_t vm_sv_builtins[] = {
3210 NULL, // #0 NULL function (not callable) (QUAKE)
3211 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3212 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3213 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3214 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3215 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3216 VM_break, // #6 void() break (QUAKE)
3217 VM_random, // #7 float() random (QUAKE)
3218 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3219 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3220 VM_error, // #10 void(string e) error (QUAKE)
3221 VM_objerror, // #11 void(string e) objerror (QUAKE)
3222 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3223 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3224 VM_spawn, // #14 entity() spawn (QUAKE)
3225 VM_remove, // #15 void(entity e) remove (QUAKE)
3226 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3227 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3228 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3229 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3230 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3231 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3232 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3233 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3234 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3235 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3236 VM_ftos, // #26 string(float f) ftos (QUAKE)
3237 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3238 VM_coredump, // #28 void() coredump (QUAKE)
3239 VM_traceon, // #29 void() traceon (QUAKE)
3240 VM_traceoff, // #30 void() traceoff (QUAKE)
3241 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3242 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3243 NULL, // #33 (QUAKE)
3244 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3245 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3246 VM_rint, // #36 float(float v) rint (QUAKE)
3247 VM_floor, // #37 float(float v) floor (QUAKE)
3248 VM_ceil, // #38 float(float v) ceil (QUAKE)
3249 NULL, // #39 (QUAKE)
3250 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3251 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3252 NULL, // #42 (QUAKE)
3253 VM_fabs, // #43 float(float f) fabs (QUAKE)
3254 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3255 VM_cvar, // #45 float(string s) cvar (QUAKE)
3256 VM_localcmd_server, // #46 void(string s) localcmd (QUAKE)
3257 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3258 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3259 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3260 NULL, // #50 (QUAKE)
3261 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3262 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3263 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3264 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3265 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3266 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3267 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3268 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3269 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3270 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3271 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3272 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3273 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3274 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3275 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3276 NULL, // #66 (QUAKE)
3277 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3278 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3279 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3280 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3281 NULL, // #71 (QUAKE)
3282 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3283 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3284 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3285 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3286 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3287 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3288 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3289 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3290 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3291 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3292 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3293 NULL, // #83 (QUAKE)
3294 NULL, // #84 (QUAKE)
3295 NULL, // #85 (QUAKE)
3296 NULL, // #86 (QUAKE)
3297 NULL, // #87 (QUAKE)
3298 NULL, // #88 (QUAKE)
3299 NULL, // #89 (QUAKE)
3300 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3301 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3302 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3303 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3304 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3305 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3306 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3307 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3308 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3309 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3310 // FrikaC and Telejano range #100-#199
3321 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3322 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3323 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3324 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3325 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3326 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3327 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3328 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3329 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3330 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3411 // FTEQW range #200-#299
3430 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3433 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3434 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3435 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3436 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3437 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3438 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3439 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3440 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3441 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3442 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3444 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3452 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3475 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.
3476 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
3477 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3478 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3479 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)
3480 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
3481 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)
3482 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)
3483 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)
3484 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)
3485 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)
3486 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
3487 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)
3488 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
3489 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.
3512 // CSQC range #300-#399
3513 NULL, // #300 void() clearscene (EXT_CSQC)
3514 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3515 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3516 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3517 NULL, // #304 void() renderscene (EXT_CSQC)
3518 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3519 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3520 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3521 NULL, // #308 void() R_EndPolygon
3523 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3524 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3528 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3529 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3530 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3531 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3532 NULL, // #319 void(string name) freepic (EXT_CSQC)
3533 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3534 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3535 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3536 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3537 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3538 NULL, // #325 void(void) drawresetcliparea
3543 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3544 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3545 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3546 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3547 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3548 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3549 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3550 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3551 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3552 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3553 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3554 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3555 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3556 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3557 NULL, // #344 vector() getmousepos (EXT_CSQC)
3558 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3559 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3560 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3561 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3562 NULL, // #349 float() isdemo (EXT_CSQC)
3563 VM_isserver, // #350 float() isserver (EXT_CSQC)
3564 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3565 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3566 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3567 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3573 NULL, // #360 float() readbyte (EXT_CSQC)
3574 NULL, // #361 float() readchar (EXT_CSQC)
3575 NULL, // #362 float() readshort (EXT_CSQC)
3576 NULL, // #363 float() readlong (EXT_CSQC)
3577 NULL, // #364 float() readcoord (EXT_CSQC)
3578 NULL, // #365 float() readangle (EXT_CSQC)
3579 NULL, // #366 string() readstring (EXT_CSQC)
3580 NULL, // #367 float() readfloat (EXT_CSQC)
3613 // LadyHavoc's range #400-#499
3614 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3615 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3616 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3617 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3618 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3619 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3620 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3621 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3622 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)
3623 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3624 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3625 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3626 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3627 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3628 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3629 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3630 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3631 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3632 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3633 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3634 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3635 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3636 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3637 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3638 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3639 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3640 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3641 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3642 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3643 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3644 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3645 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3646 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3647 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3648 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3649 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3650 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3651 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3652 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3653 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3654 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3655 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3656 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3657 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3658 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3659 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3660 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3661 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3662 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3663 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3664 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3665 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3666 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3667 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3668 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3669 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3670 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3671 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3673 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3674 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3675 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3676 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3677 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3678 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3679 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3680 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3681 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3682 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3683 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3685 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3686 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3687 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3688 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3689 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3690 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3691 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3692 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3693 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3694 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3695 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3696 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3697 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3698 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3699 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3700 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3708 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3709 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3710 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3711 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3712 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3713 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3714 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3715 VM_SV_WritePicture, // #501
3717 VM_whichpack, // #503 string(string) whichpack = #503;
3724 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3725 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3726 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3727 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)
3728 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3729 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3730 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3731 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3732 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3733 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3743 VM_loadfromdata, // #529
3744 VM_loadfromfile, // #530
3745 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3747 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3748 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3749 VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP)
3750 VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP)
3751 VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP)
3752 VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP)
3754 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3755 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3756 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3819 VM_callfunction, // #605
3820 VM_writetofile, // #606
3821 VM_isfunction, // #607
3827 VM_parseentitydata, // #613
3838 VM_SV_getextresponse, // #624 string getextresponse(void)
3841 VM_sprintf, // #627 string sprintf(string format, ...)
3842 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3843 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3853 VM_digest_hex, // #639
3856 VM_coverage, // #642
3860 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3862 void SVVM_init_cmd(prvm_prog_t *prog)
3867 void SVVM_reset_cmd(prvm_prog_t *prog)
3869 World_End(&sv.world);
3871 if(prog->loaded && PRVM_serverfunction(SV_Shutdown))
3873 func_t s = PRVM_serverfunction(SV_Shutdown);
3874 PRVM_serverglobalfloat(time) = sv.time;
3875 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3876 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");