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",
231 "DP_QC_FS_SEARCH_PACKFILE",
234 //"EXT_CSQC" // not ready yet
241 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.
243 setorigin (entity, origin)
246 static void VM_SV_setorigin(prvm_prog_t *prog)
250 VM_SAFEPARMCOUNT(2, VM_SV_setorigin);
252 e = PRVM_G_EDICT(OFS_PARM0);
253 if (e == prog->edicts)
255 VM_Warning(prog, "setorigin: can not modify world entity\n");
260 VM_Warning(prog, "setorigin: can not modify free entity\n");
263 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), PRVM_serveredictvector(e, origin));
264 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
265 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
269 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
270 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qbool rotate)
274 for (i=0 ; i<3 ; i++)
276 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
278 // set derived values
279 VectorCopy (min, PRVM_serveredictvector(e, mins));
280 VectorCopy (max, PRVM_serveredictvector(e, maxs));
281 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
290 the size box is rotated by the current angle
291 LadyHavoc: no it isn't...
293 setsize (entity, minvector, maxvector)
296 static void VM_SV_setsize(prvm_prog_t *prog)
301 VM_SAFEPARMCOUNT(3, VM_SV_setsize);
303 e = PRVM_G_EDICT(OFS_PARM0);
304 if (e == prog->edicts)
306 VM_Warning(prog, "setsize: can not modify world entity\n");
311 VM_Warning(prog, "setsize: can not modify free entity\n");
314 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), mins);
315 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), maxs);
316 SetMinMaxSize(prog, e, mins, maxs, false);
324 setmodel(entity, model)
327 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
328 static void VM_SV_setmodel(prvm_prog_t *prog)
334 VM_SAFEPARMCOUNT(2, VM_SV_setmodel);
336 e = PRVM_G_EDICT(OFS_PARM0);
337 if (e == prog->edicts)
339 VM_Warning(prog, "setmodel: can not modify world entity\n");
344 VM_Warning(prog, "setmodel: can not modify free entity\n");
347 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
348 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
349 PRVM_serveredictfloat(e, modelindex) = i;
351 mod = SV_GetModelByIndex(i);
355 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
356 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
358 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
361 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
368 single print to a specific client
370 sprint(clientent, value)
373 static void VM_SV_sprint(prvm_prog_t *prog)
377 char string[VM_STRINGTEMP_LENGTH];
379 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
381 VM_VarString(prog, 1, string, sizeof(string));
383 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
384 // LadyHavoc: div0 requested that sprintto world operate like print
391 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
393 VM_Warning(prog, "tried to centerprint to a non-client\n");
397 client = svs.clients + entnum-1;
398 if (!client->netconnection)
401 MSG_WriteChar(&client->netconnection->message,svc_print);
402 MSG_WriteString(&client->netconnection->message, string);
410 single print to a specific client
412 centerprint(clientent, value)
415 static void VM_SV_centerprint(prvm_prog_t *prog)
419 char string[VM_STRINGTEMP_LENGTH];
421 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
423 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
425 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
427 VM_Warning(prog, "tried to centerprint to a non-client\n");
431 client = svs.clients + entnum-1;
432 if (!client->netconnection)
435 VM_VarString(prog, 1, string, sizeof(string));
436 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
437 MSG_WriteString(&client->netconnection->message, string);
444 particle(origin, color, count)
447 static void VM_SV_particle(prvm_prog_t *prog)
453 VM_SAFEPARMCOUNT(4, VM_SV_particle);
455 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
456 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
457 color = (int)PRVM_G_FLOAT(OFS_PARM2);
458 count = (int)PRVM_G_FLOAT(OFS_PARM3);
459 SV_StartParticle (org, dir, color, count);
469 static void VM_SV_ambientsound(prvm_prog_t *prog)
473 prvm_vec_t vol, attenuation;
476 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
478 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
479 samp = PRVM_G_STRING(OFS_PARM1);
480 vol = PRVM_G_FLOAT(OFS_PARM2);
481 attenuation = PRVM_G_FLOAT(OFS_PARM3);
483 // check to see if samp was properly precached
484 soundnum = SV_SoundIndex(samp, 1);
492 if(sv.protocol == PROTOCOL_NEHAHRABJP)
495 // add an svc_spawnambient command to the level signon packet
498 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
500 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
502 MSG_WriteVector(&sv.signon, pos, sv.protocol);
504 if (large || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
505 MSG_WriteShort (&sv.signon, soundnum);
507 MSG_WriteByte (&sv.signon, soundnum);
509 MSG_WriteByte (&sv.signon, (int)(vol*255));
510 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
518 Each entity can have eight independant sound sources, like voice,
521 Channel 0 is an auto-allocate channel, the others override anything
522 already running on that entity/channel pair.
524 An attenuation of 0 will play full volume everywhere in the level.
525 Larger attenuations will drop off.
527 void(entity e, float chan, string samp, float volume[, float atten[, float pitchchange[, float flags]]]) sound (QUAKE)
530 static void VM_SV_sound(prvm_prog_t *prog)
534 prvm_edict_t *entity;
540 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
542 entity = PRVM_G_EDICT(OFS_PARM0);
543 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
544 sample = PRVM_G_STRING(OFS_PARM2);
545 nvolume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
548 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
552 attenuation = PRVM_G_FLOAT(OFS_PARM4);
556 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
561 if(channel >= 8 && channel <= 15) // weird QW feature
563 flags |= CHANNELFLAG_RELIABLE;
569 // LadyHavoc: we only let the qc set certain flags, others are off-limits
570 flags = (int)PRVM_G_FLOAT(OFS_PARM6) & (CHANNELFLAG_RELIABLE | CHANNELFLAG_FORCELOOP | CHANNELFLAG_PAUSED | CHANNELFLAG_FULLVOLUME);
573 if (nvolume < 0 || nvolume > 255)
575 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
579 if (attenuation < 0 || attenuation > 4)
581 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
585 channel = CHAN_USER2ENGINE(channel);
587 if (!IS_CHAN(channel))
589 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
593 SV_StartSound (entity, channel, sample, nvolume, attenuation, flags & CHANNELFLAG_RELIABLE, pitchchange);
600 Follows the same logic as VM_SV_sound, except instead of
601 an entity, an origin for the sound is provided, and channel
602 is omitted (since no entity is being tracked).
606 static void VM_SV_pointsound(prvm_prog_t *prog)
614 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
616 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
617 sample = PRVM_G_STRING(OFS_PARM1);
618 nvolume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
619 attenuation = PRVM_G_FLOAT(OFS_PARM3);
620 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
622 if (nvolume < 0 || nvolume > 255)
624 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
628 if (attenuation < 0 || attenuation > 4)
630 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
634 SV_StartPointSound (org, sample, nvolume, attenuation, pitchchange);
641 Used for use tracing and shot targeting
642 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
643 if the tryents flag is set.
645 traceline (vector1, vector2, movetype, ignore)
648 static void VM_SV_traceline(prvm_prog_t *prog)
655 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
657 prog->xfunction->builtinsprofile += 30;
659 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
660 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), v2);
661 move = (int)PRVM_G_FLOAT(OFS_PARM2);
662 ent = PRVM_G_EDICT(OFS_PARM3);
664 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]))
665 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));
667 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtracelinelength.value);
669 VM_SetTraceGlobals(prog, &trace);
677 Used for use tracing and shot targeting
678 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
679 if the tryents flag is set.
681 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
684 // LadyHavoc: added this for my own use, VERY useful, similar to traceline
685 static void VM_SV_tracebox(prvm_prog_t *prog)
687 vec3_t v1, v2, m1, m2;
692 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
694 prog->xfunction->builtinsprofile += 30;
696 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
697 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), m1);
698 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), m2);
699 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), v2);
700 move = (int)PRVM_G_FLOAT(OFS_PARM4);
701 ent = PRVM_G_EDICT(OFS_PARM5);
703 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]))
704 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));
706 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtraceboxlength.value);
708 VM_SetTraceGlobals(prog, &trace);
711 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
715 vec3_t move, end, tossentorigin, tossentmins, tossentmaxs;
716 vec3_t original_origin;
717 vec3_t original_velocity;
718 vec3_t original_angles;
719 vec3_t original_avelocity;
722 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
723 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
724 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
725 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
727 gravity = PRVM_serveredictfloat(tossent, gravity);
730 gravity *= sv_gravity.value * 0.025;
732 for (i = 0;i < 200;i++) // LadyHavoc: sanity check; never trace more than 10 seconds
734 SV_CheckVelocity (tossent);
735 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
736 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
737 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
738 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
739 VectorCopy(PRVM_serveredictvector(tossent, origin), tossentorigin);
740 VectorCopy(PRVM_serveredictvector(tossent, mins), tossentmins);
741 VectorCopy(PRVM_serveredictvector(tossent, maxs), tossentmaxs);
742 trace = SV_TraceBox(tossentorigin, tossentmins, tossentmaxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent), 0, 0, collision_extendmovelength.value);
743 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
744 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
746 if (trace.fraction < 1)
750 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
751 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
752 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
753 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
758 static void VM_SV_tracetoss(prvm_prog_t *prog)
762 prvm_edict_t *ignore;
764 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
766 prog->xfunction->builtinsprofile += 600;
768 ent = PRVM_G_EDICT(OFS_PARM0);
769 if (ent == prog->edicts)
771 VM_Warning(prog, "tracetoss: can not use world entity\n");
774 ignore = PRVM_G_EDICT(OFS_PARM1);
776 trace = SV_Trace_Toss(prog, ent, ignore);
778 VM_SetTraceGlobals(prog, &trace);
781 //============================================================================
783 static int checkpvsbytes;
784 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
786 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
792 // cycle to the next one
794 check = bound(1, check, svs.maxclients);
795 if (check == svs.maxclients)
803 prog->xfunction->builtinsprofile++;
805 if (i == svs.maxclients+1)
807 // look up the client's edict
808 ent = PRVM_EDICT_NUM(i);
809 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
810 if (i != check && (ent->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
812 // found a valid client (possibly the same one again)
816 // get the PVS for the entity
817 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
819 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
820 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
829 Returns a client (or object that has a client enemy) that would be a
832 If there is more than one valid option, they are cycled each frame
834 If (self.origin + self.viewofs) is not in the PVS of the current target,
835 it is not returned at all.
840 int c_invis, c_notvis;
841 static void VM_SV_checkclient(prvm_prog_t *prog)
843 prvm_edict_t *ent, *self;
846 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
848 // find a new check if on a new frame
849 if (sv.time - sv.lastchecktime >= 0.1)
851 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
852 sv.lastchecktime = sv.time;
855 // return check if it might be visible
856 ent = PRVM_EDICT_NUM(sv.lastcheck);
857 if (ent->free || PRVM_serveredictfloat(ent, health) <= 0)
859 VM_RETURN_EDICT(prog->edicts);
863 // if current entity can't possibly see the check entity, return 0
864 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
865 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
866 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
869 VM_RETURN_EDICT(prog->edicts);
873 // might be able to see it
875 VM_RETURN_EDICT(ent);
878 //============================================================================
884 Checks if an entity is in a point's PVS.
885 Should be fast but can be inexact.
887 float checkpvs(vector viewpos, entity viewee) = #240;
890 static void VM_SV_checkpvs(prvm_prog_t *prog)
892 vec3_t viewpos, absmin, absmax;
893 prvm_edict_t *viewee;
898 unsigned char fatpvs[MAX_MAP_LEAFS/8];
901 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
902 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
903 viewee = PRVM_G_EDICT(OFS_PARM1);
907 VM_Warning(prog, "checkpvs: can not check free entity\n");
908 PRVM_G_FLOAT(OFS_RETURN) = 4;
913 if(!sv.worldmodel || !sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
915 // no PVS support on this worldmodel... darn
916 PRVM_G_FLOAT(OFS_RETURN) = 3;
919 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
922 // viewpos isn't in any PVS... darn
923 PRVM_G_FLOAT(OFS_RETURN) = 2;
926 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
927 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
928 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, absmin, absmax);
930 // using fat PVS like FTEQW does (slow)
931 if(!sv.worldmodel || !sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
933 // no PVS support on this worldmodel... darn
934 PRVM_G_FLOAT(OFS_RETURN) = 3;
937 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
940 // viewpos isn't in any PVS... darn
941 PRVM_G_FLOAT(OFS_RETURN) = 2;
944 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
945 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
946 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, absmin, absmax);
955 Sends text over to the client's execution buffer
957 stuffcmd (clientent, value, ...)
960 static void VM_SV_stuffcmd(prvm_prog_t *prog)
964 char string[VM_STRINGTEMP_LENGTH];
966 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
968 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
969 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
971 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
975 VM_VarString(prog, 1, string, sizeof(string));
978 host_client = svs.clients + entnum-1;
979 SV_ClientCommands ("%s", string);
987 Returns a chain of entities that have origins within a spherical area
989 findradius (origin, radius)
992 static void VM_SV_findradius(prvm_prog_t *prog)
994 prvm_edict_t *ent, *chain;
995 vec_t radius, radius2;
996 vec3_t org, eorg, mins, maxs;
999 static prvm_edict_t *touchedicts[MAX_EDICTS];
1002 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
1005 chainfield = PRVM_G_INT(OFS_PARM2);
1007 chainfield = prog->fieldoffsets.chain;
1009 prog->error_cmd("VM_SV_findradius: %s doesnt have the specified chain field !", prog->name);
1011 chain = (prvm_edict_t *)prog->edicts;
1013 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1014 radius = PRVM_G_FLOAT(OFS_PARM1);
1015 radius2 = radius * radius;
1017 mins[0] = org[0] - (radius + 1);
1018 mins[1] = org[1] - (radius + 1);
1019 mins[2] = org[2] - (radius + 1);
1020 maxs[0] = org[0] + (radius + 1);
1021 maxs[1] = org[1] + (radius + 1);
1022 maxs[2] = org[2] + (radius + 1);
1023 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1024 if (numtouchedicts > MAX_EDICTS)
1026 // this never happens
1027 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1028 numtouchedicts = MAX_EDICTS;
1030 for (i = 0;i < numtouchedicts;i++)
1032 ent = touchedicts[i];
1033 prog->xfunction->builtinsprofile++;
1034 // Quake did not return non-solid entities but darkplaces does
1035 // (note: this is the reason you can't blow up fallen zombies)
1036 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1038 // LadyHavoc: compare against bounding box rather than center so it
1039 // doesn't miss large objects, and use DotProduct instead of Length
1040 // for a major speedup
1041 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1042 if (sv_gameplayfix_findradiusdistancetobox.integer)
1044 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1045 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1046 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1049 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1050 if (DotProduct(eorg, eorg) < radius2)
1052 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1057 VM_RETURN_EDICT(chain);
1064 Returns a chain of entities that are touching a box (a simpler findradius); supports DP_QC_FINDCHAIN_TOFIELD
1066 findbox (mins, maxs)
1069 static void VM_SV_findbox(prvm_prog_t *prog)
1071 prvm_edict_t *chain;
1072 int i, numtouchedicts;
1073 static prvm_edict_t *touchedicts[MAX_EDICTS];
1076 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findbox);
1079 chainfield = PRVM_G_INT(OFS_PARM2);
1081 chainfield = prog->fieldoffsets.chain;
1083 prog->error_cmd("VM_SV_findbox: %s doesnt have the specified chain field !", prog->name);
1085 chain = (prvm_edict_t *)prog->edicts;
1087 numtouchedicts = SV_EntitiesInBox(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), MAX_EDICTS, touchedicts);
1088 if (numtouchedicts > MAX_EDICTS)
1090 // this never happens
1091 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1092 numtouchedicts = MAX_EDICTS;
1094 for (i = 0; i < numtouchedicts; ++i)
1096 prog->xfunction->builtinsprofile++;
1097 PRVM_EDICTFIELDEDICT(touchedicts[i], chainfield) = PRVM_EDICT_TO_PROG(chain);
1098 chain = touchedicts[i];
1101 VM_RETURN_EDICT(chain);
1104 static void VM_SV_precache_sound(prvm_prog_t *prog)
1106 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1107 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1110 static void VM_SV_precache_model(prvm_prog_t *prog)
1112 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1113 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1114 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1121 float(float yaw, float dist[, settrace]) walkmove
1124 static void VM_SV_walkmove(prvm_prog_t *prog)
1133 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1135 // assume failure if it returns early
1136 PRVM_G_FLOAT(OFS_RETURN) = 0;
1138 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1139 if (ent == prog->edicts)
1141 VM_Warning(prog, "walkmove: can not modify world entity\n");
1146 VM_Warning(prog, "walkmove: can not modify free entity\n");
1149 yaw = PRVM_G_FLOAT(OFS_PARM0);
1150 dist = PRVM_G_FLOAT(OFS_PARM1);
1151 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1153 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1156 yaw = yaw*M_PI*2 / 360;
1158 move[0] = cos(yaw)*dist;
1159 move[1] = sin(yaw)*dist;
1162 // save program state, because SV_movestep may call other progs
1163 oldf = prog->xfunction;
1164 oldself = PRVM_serverglobaledict(self);
1166 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1169 // restore program state
1170 prog->xfunction = oldf;
1171 PRVM_serverglobaledict(self) = oldself;
1182 static void VM_SV_droptofloor(prvm_prog_t *prog)
1185 vec3_t end, entorigin, entmins, entmaxs;
1188 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1190 // assume failure if it returns early
1191 PRVM_G_FLOAT(OFS_RETURN) = 0;
1193 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1194 if (ent == prog->edicts)
1196 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1201 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1205 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1206 if (sv.worldmodel->brush.isq3bsp)
1208 else if (sv.worldmodel->brush.isq2bsp)
1211 end[2] -= 256; // Quake, QuakeWorld
1213 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1214 PHYS_NudgeOutOfSolid(prog, ent);
1216 VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
1217 VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
1218 VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
1219 trace = SV_TraceBox(entorigin, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
1220 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1223 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]);
1224 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1225 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
1226 VectorSubtract(trace.endpos, offset, trace.endpos);
1227 if (trace.startsolid)
1229 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]);
1231 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1232 PRVM_serveredictedict(ent, groundentity) = 0;
1233 PRVM_G_FLOAT(OFS_RETURN) = 1;
1235 else if (trace.fraction < 1)
1237 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]);
1238 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1239 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1240 PHYS_NudgeOutOfSolid(prog, ent);
1242 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1243 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1244 PRVM_G_FLOAT(OFS_RETURN) = 1;
1245 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1246 ent->priv.server->suspendedinairflag = true;
1251 if (!trace.allsolid && trace.fraction < 1)
1253 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1255 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1256 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1257 PRVM_G_FLOAT(OFS_RETURN) = 1;
1258 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1259 ent->priv.server->suspendedinairflag = true;
1268 void(float style, string value) lightstyle
1271 static void VM_SV_lightstyle(prvm_prog_t *prog)
1278 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1280 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1281 val = PRVM_G_STRING(OFS_PARM1);
1283 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1284 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1287 // change the string in sv
1288 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1290 // send message to all clients on this server
1291 if (sv.state != ss_active)
1294 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1296 if (client->active && client->netconnection)
1298 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1299 MSG_WriteChar (&client->netconnection->message,style);
1300 MSG_WriteString (&client->netconnection->message, val);
1310 static void VM_SV_checkbottom(prvm_prog_t *prog)
1312 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1313 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1321 static void VM_SV_pointcontents(prvm_prog_t *prog)
1324 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1325 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point);
1326 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(SV_PointSuperContents(point));
1333 Pick a vector for the player to shoot along
1334 vector aim(entity, missilespeed)
1337 static void VM_SV_aim(prvm_prog_t *prog)
1339 prvm_edict_t *ent, *check, *bestent;
1340 vec3_t start, dir, end, bestdir;
1343 float dist, bestdist;
1346 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1348 // assume failure if it returns early
1349 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1350 // if sv_aim is so high it can't possibly accept anything, skip out early
1351 if (sv_aim.value >= 1)
1354 ent = PRVM_G_EDICT(OFS_PARM0);
1355 if (ent == prog->edicts)
1357 VM_Warning(prog, "aim: can not use world entity\n");
1362 VM_Warning(prog, "aim: can not use free entity\n");
1365 //speed = PRVM_G_FLOAT(OFS_PARM1);
1367 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1370 // try sending a trace straight
1371 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1372 VectorMA (start, 2048, dir, end);
1373 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1374 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1375 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1377 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1382 // try all possible entities
1383 VectorCopy (dir, bestdir);
1384 bestdist = sv_aim.value;
1387 check = PRVM_NEXT_EDICT(prog->edicts);
1388 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1390 prog->xfunction->builtinsprofile++;
1391 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1395 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1396 continue; // don't aim at teammate
1397 for (j=0 ; j<3 ; j++)
1398 end[j] = PRVM_serveredictvector(check, origin)[j]
1399 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1400 VectorSubtract (end, start, dir);
1401 VectorNormalize (dir);
1402 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1403 if (dist < bestdist)
1404 continue; // to far to turn
1405 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1406 if (tr.ent == check)
1407 { // can shoot at this one
1415 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1416 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1417 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1419 VectorNormalize (end);
1420 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1424 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1429 ===============================================================================
1433 ===============================================================================
1436 #define MSG_BROADCAST 0 // unreliable to all
1437 #define MSG_ONE 1 // reliable to one (msg_entity)
1438 #define MSG_ALL 2 // reliable to all
1439 #define MSG_INIT 3 // write to the init string
1440 #define MSG_ENTITY 5
1442 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1448 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1452 return &sv.datagram;
1455 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1456 entnum = PRVM_NUM_FOR_EDICT(ent);
1457 if (entnum < 1 || entnum > svs.maxclients)
1459 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1460 return &sv.reliable_datagram;
1462 else if (!svs.clients[entnum-1].active)
1464 VM_Warning(prog, "WriteDest: tried to write to a disconnected client\n");
1465 return &sv.reliable_datagram;
1467 else if (!svs.clients[entnum-1].netconnection)
1469 VM_Warning(prog, "WriteDest: tried to write to a bot client\n");
1470 return &sv.reliable_datagram;
1473 return &svs.clients[entnum-1].netconnection->message;
1476 VM_Warning(prog, "WriteDest: bad destination\n");
1478 return &sv.reliable_datagram;
1484 return sv.writeentitiestoclient_msg;
1490 static void VM_SV_WriteByte(prvm_prog_t *prog)
1492 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1493 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1496 static void VM_SV_WriteChar(prvm_prog_t *prog)
1498 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1499 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1502 static void VM_SV_WriteShort(prvm_prog_t *prog)
1504 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1505 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1508 static void VM_SV_WriteLong(prvm_prog_t *prog)
1510 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1511 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1514 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1516 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1517 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1520 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1522 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1523 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1526 static void VM_SV_WriteString(prvm_prog_t *prog)
1528 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1529 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1532 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1534 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1535 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1539 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1541 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1542 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1545 // writes a picture as at most size bytes of data
1547 // IMGNAME \0 SIZE(short) IMGDATA
1548 // if failed to read/compress:
1550 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1551 static void VM_SV_WritePicture(prvm_prog_t *prog)
1553 const char *imgname;
1557 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1559 imgname = PRVM_G_STRING(OFS_PARM1);
1560 size = (size_t) PRVM_G_FLOAT(OFS_PARM2);
1564 MSG_WriteString(WriteDest(prog), imgname);
1565 if(Image_Compress(imgname, size, &buf, &size))
1568 MSG_WriteShort(WriteDest(prog), (int)size);
1569 SZ_Write(WriteDest(prog), (unsigned char *) buf, (int)size);
1574 MSG_WriteShort(WriteDest(prog), 0);
1578 //////////////////////////////////////////////////////////
1580 static void VM_SV_makestatic(prvm_prog_t *prog)
1585 // allow 0 parameters due to an id1 qc bug in which this function is used
1586 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1587 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1589 if (prog->argc >= 1)
1590 ent = PRVM_G_EDICT(OFS_PARM0);
1592 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1593 if (ent == prog->edicts)
1595 VM_Warning(prog, "makestatic: can not modify world entity\n");
1600 VM_Warning(prog, "makestatic: can not modify free entity\n");
1605 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1608 if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1610 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1611 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1612 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1616 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1617 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1618 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1622 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1623 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1624 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1627 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1628 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1629 for (i=0 ; i<3 ; i++)
1631 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1632 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1635 // throw the entity away now
1636 PRVM_ED_Free(prog, ent);
1639 //=============================================================================
1646 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1652 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1654 ent = PRVM_G_EDICT(OFS_PARM0);
1655 i = PRVM_NUM_FOR_EDICT(ent);
1656 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1658 Con_Print("tried to setspawnparms on a non-client\n");
1662 // copy spawn parms out of the client_t
1663 client = svs.clients + i-1;
1664 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1665 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1672 Returns a color vector indicating the lighting at the requested point.
1674 (Internal Operation note: actually measures the light beneath the point, just like
1675 the model lighting on the client)
1680 static void VM_SV_getlight(prvm_prog_t *prog)
1682 vec3_t ambientcolor, diffusecolor, diffusenormal;
1684 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1685 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
1686 VectorClear(ambientcolor);
1687 VectorClear(diffusecolor);
1688 VectorClear(diffusenormal);
1689 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1690 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1691 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1696 unsigned char type; // 1/2/8 or 0 to indicate unused
1700 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)
1701 static int vm_customstats_last;
1703 void VM_CustomStats_Clear (void)
1705 memset(vm_customstats, 0, sizeof(vm_customstats));
1706 vm_customstats_last = -1;
1709 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1711 prvm_prog_t *prog = SVVM_prog;
1719 for(i=MIN_VM_STAT; i<=vm_customstats_last ;i++)
1721 if(!vm_customstats[i].type)
1723 switch(vm_customstats[i].type)
1725 //string as 16 bytes
1728 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1729 stats[i] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1730 stats[i+1] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1731 stats[i+2] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1732 stats[i+3] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1734 //float field sent as-is
1736 // 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
1737 u.f = PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1740 //integer value of float field
1742 stats[i] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1750 extern cvar_t sv_gameplayfix_customstats;
1752 // void(float index, float type, .void field) SV_AddStat = #232;
1753 // Set up an auto-sent player stat.
1754 // Client's get thier own fields sent to them. Index may not be less than 32.
1755 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1756 // 1: string (4 stats carrying a total of 16 charactures)
1757 // 2: float (one stat, float converted to an integer for transportation)
1758 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1759 static void VM_SV_AddStat(prvm_prog_t *prog)
1763 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1765 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1766 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1767 off = PRVM_G_INT (OFS_PARM2);
1776 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);
1782 VM_Warning(prog, "PF_SV_AddStat: index (%i) may not be less than %i\n", i, MIN_VM_STAT);
1786 if (i >= MAX_CL_STATS)
1788 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);
1792 if (i > (MAX_CL_STATS - 4) && type == 1)
1794 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);
1798 // these are hazardous to override but sort of allowed if one wants to be adventurous... and enjoys warnings.
1799 if (i < MIN_VM_STAT)
1800 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);
1801 else if (i >= MAX_VM_STAT && !sv_gameplayfix_customstats.integer)
1802 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);
1803 else if (i > (MAX_VM_STAT - 4) && type == 1 && !sv_gameplayfix_customstats.integer)
1804 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);
1806 vm_customstats[i].type = type;
1807 vm_customstats[i].fieldoffset = off;
1808 if(vm_customstats_last < i)
1809 vm_customstats_last = i;
1816 copies data from one entity to another
1818 copyentity(src, dst)
1821 static void VM_SV_copyentity(prvm_prog_t *prog)
1823 prvm_edict_t *in, *out;
1824 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1825 in = PRVM_G_EDICT(OFS_PARM0);
1826 if (in == prog->edicts)
1828 VM_Warning(prog, "copyentity: can not read world entity\n");
1833 VM_Warning(prog, "copyentity: can not read free entity\n");
1836 out = PRVM_G_EDICT(OFS_PARM1);
1837 if (out == prog->edicts)
1839 VM_Warning(prog, "copyentity: can not modify world entity\n");
1844 VM_Warning(prog, "copyentity: can not modify free entity\n");
1847 memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
1857 sets the color of a client and broadcasts the update to all connected clients
1859 setcolor(clientent, value)
1862 static void VM_SV_setcolor(prvm_prog_t *prog)
1867 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1868 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1869 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1871 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1873 Con_Print("tried to setcolor a non-client\n");
1877 client = svs.clients + entnum-1;
1880 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1881 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1884 if (client->old_colors != client->colors)
1886 client->old_colors = client->colors;
1887 // send notification to all clients
1888 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1889 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1890 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1898 effect(origin, modelname, startframe, framecount, framerate)
1901 static void VM_SV_effect(prvm_prog_t *prog)
1906 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1907 s = PRVM_G_STRING(OFS_PARM1);
1910 VM_Warning(prog, "effect: no model specified\n");
1914 i = SV_ModelIndex(s, 1);
1917 VM_Warning(prog, "effect: model not precached\n");
1921 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1923 VM_Warning(prog, "effect: framecount < 1\n");
1927 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1929 VM_Warning(prog, "effect: framerate < 1\n");
1933 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1934 SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1937 static void VM_SV_te_blood(prvm_prog_t *prog)
1939 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1940 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1942 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1943 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1945 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1949 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1950 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1951 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1953 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1954 SV_FlushBroadcastMessages();
1957 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1959 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1960 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1962 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1963 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1965 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1970 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1973 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1975 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1976 SV_FlushBroadcastMessages();
1979 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1981 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1982 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1983 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1985 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1989 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1990 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1991 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1992 SV_FlushBroadcastMessages();
1995 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1997 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1998 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2000 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2001 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2004 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2005 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2007 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2008 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2009 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2011 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2012 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2015 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2017 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2018 // gravity true/false
2019 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
2021 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
2022 SV_FlushBroadcastMessages();
2025 static void VM_SV_te_particlerain(prvm_prog_t *prog)
2027 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
2028 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2030 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2031 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2033 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2034 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2035 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2037 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2038 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2039 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2041 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2042 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2043 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2045 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2047 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2048 SV_FlushBroadcastMessages();
2051 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
2053 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
2054 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2056 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2057 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2059 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2060 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2061 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2063 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2064 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2065 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2067 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2068 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2069 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2071 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2073 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2074 SV_FlushBroadcastMessages();
2077 static void VM_SV_te_spark(prvm_prog_t *prog)
2079 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
2080 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2082 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2083 MSG_WriteByte(&sv.datagram, TE_SPARK);
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);
2089 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2090 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2091 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2093 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2094 SV_FlushBroadcastMessages();
2097 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2099 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2100 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2101 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2103 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2104 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2105 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2106 SV_FlushBroadcastMessages();
2109 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2111 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2112 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2113 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2115 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2116 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2117 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2118 SV_FlushBroadcastMessages();
2121 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2123 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2124 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2125 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2127 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2128 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2129 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2130 SV_FlushBroadcastMessages();
2133 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2135 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2136 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2137 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2139 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2140 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2141 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2142 SV_FlushBroadcastMessages();
2145 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2147 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2148 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2149 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2151 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2152 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2153 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2154 SV_FlushBroadcastMessages();
2157 static void VM_SV_te_customflash(prvm_prog_t *prog)
2159 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2160 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2162 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2163 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2165 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2166 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2167 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2169 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2171 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2173 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2174 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2175 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2176 SV_FlushBroadcastMessages();
2179 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2181 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2182 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2183 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2185 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2186 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2187 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2188 SV_FlushBroadcastMessages();
2191 static void VM_SV_te_spike(prvm_prog_t *prog)
2193 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2194 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2195 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2197 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2198 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2199 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2200 SV_FlushBroadcastMessages();
2203 static void VM_SV_te_superspike(prvm_prog_t *prog)
2205 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2206 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2207 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2209 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2210 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2211 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2212 SV_FlushBroadcastMessages();
2215 static void VM_SV_te_explosion(prvm_prog_t *prog)
2217 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2218 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2219 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2221 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2222 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2223 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2224 SV_FlushBroadcastMessages();
2227 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2229 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2230 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2231 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2234 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2235 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2236 SV_FlushBroadcastMessages();
2239 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2241 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2242 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2243 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2245 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2246 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2247 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2248 SV_FlushBroadcastMessages();
2251 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2253 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2254 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2255 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2257 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2258 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2259 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2260 SV_FlushBroadcastMessages();
2263 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2265 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2266 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2267 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2269 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2270 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2271 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2272 SV_FlushBroadcastMessages();
2275 static void VM_SV_te_teleport(prvm_prog_t *prog)
2277 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2278 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2279 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2281 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2282 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2283 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2284 SV_FlushBroadcastMessages();
2287 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2289 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2290 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2291 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2293 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2294 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2295 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2297 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2298 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2299 SV_FlushBroadcastMessages();
2302 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2304 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2305 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2306 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
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_lightning2(prvm_prog_t *prog)
2322 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2323 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2324 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2326 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2328 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2329 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2330 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2332 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2333 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2334 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2335 SV_FlushBroadcastMessages();
2338 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2340 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2341 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2342 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2344 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2346 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2347 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2348 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2350 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2351 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2352 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2353 SV_FlushBroadcastMessages();
2356 static void VM_SV_te_beam(prvm_prog_t *prog)
2358 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2359 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2360 MSG_WriteByte(&sv.datagram, TE_BEAM);
2362 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2364 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2365 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2366 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2368 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2369 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2370 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2371 SV_FlushBroadcastMessages();
2374 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2376 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2377 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2378 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2379 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2380 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2381 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2382 SV_FlushBroadcastMessages();
2385 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2387 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2388 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2389 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2391 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2392 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2393 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2395 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2396 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2397 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2399 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2400 SV_FlushBroadcastMessages();
2403 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2404 //this function originally written by KrimZon, made shorter by LadyHavoc
2405 static void VM_SV_clientcommand(prvm_prog_t *prog)
2407 client_t *temp_client;
2409 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2411 //find client for this entity
2412 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2413 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2415 Con_Print("PF_clientcommand: entity is not a client\n");
2419 temp_client = host_client;
2420 host_client = svs.clients + i;
2421 Cmd_ExecuteString(cmd_serverfromclient, PRVM_G_STRING(OFS_PARM1), src_client, true);
2422 host_client = temp_client;
2425 //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)
2426 static void VM_SV_setattachment(prvm_prog_t *prog)
2428 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2429 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2430 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2433 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2435 if (e == prog->edicts)
2437 VM_Warning(prog, "setattachment: can not modify world entity\n");
2442 VM_Warning(prog, "setattachment: can not modify free entity\n");
2446 if (tagentity == NULL)
2447 tagentity = prog->edicts;
2451 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2453 model = SV_GetModelFromEdict(tagentity);
2456 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2458 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);
2461 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));
2464 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2465 PRVM_serveredictfloat(e, tag_index) = tagindex;
2468 /////////////////////////////////////////
2469 // DP_MD3_TAGINFO extension coded by VorteX
2471 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2475 i = (int)PRVM_serveredictfloat(e, modelindex);
2476 if (i < 1 || i >= MAX_MODELS)
2479 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2482 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2489 Matrix4x4_CreateIdentity(tag_localmatrix);
2491 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2493 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2504 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qbool viewmatrix)
2507 float pitchsign = 1;
2509 scale = PRVM_serveredictfloat(ent, scale);
2514 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);
2517 pitchsign = SV_GetPitchSign(prog, ent);
2518 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);
2522 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2525 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2527 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2528 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2529 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2530 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2532 *out = identitymatrix;
2536 // Warnings/errors code:
2537 // 0 - normal (everything all-right)
2540 // 3 - null or non-precached model
2541 // 4 - no tags with requested index
2542 // 5 - runaway loop at attachment chain
2543 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2546 int modelindex, attachloop;
2547 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2550 *out = identitymatrix; // warnings and errors return identical matrix
2552 if (ent == prog->edicts)
2557 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2558 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2561 model = SV_GetModelByIndex(modelindex);
2563 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2564 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2565 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2567 tagmatrix = identitymatrix;
2568 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2572 if (attachloop >= 256) // prevent runaway looping
2574 // apply transformation by child's tagindex on parent entity and then
2575 // by parent entity itself
2576 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2577 if (ret && attachloop == 0)
2579 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2580 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2581 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2582 // next iteration we process the parent entity
2583 if (PRVM_serveredictedict(ent, tag_entity))
2585 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2586 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2593 // RENDER_VIEWMODEL magic
2594 if (PRVM_serveredictedict(ent, viewmodelforclient))
2596 Matrix4x4_Copy(&tagmatrix, out);
2597 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2599 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2600 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2605 //float(entity ent, string tagname) gettagindex;
2607 static void VM_SV_gettagindex(prvm_prog_t *prog)
2610 const char *tag_name;
2613 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2615 ent = PRVM_G_EDICT(OFS_PARM0);
2616 tag_name = PRVM_G_STRING(OFS_PARM1);
2618 if (ent == prog->edicts)
2620 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2625 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2630 if (!SV_GetModelFromEdict(ent))
2631 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2634 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2636 if(developer_extra.integer)
2637 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2639 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2642 //vector(entity ent, float tagindex) gettaginfo;
2643 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2647 matrix4x4_t tag_matrix;
2648 matrix4x4_t tag_localmatrix;
2650 const char *tagname;
2652 vec3_t forward, left, up, origin;
2653 const model_t *model;
2655 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2657 e = PRVM_G_EDICT(OFS_PARM0);
2658 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2660 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2661 Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
2662 VectorCopy(forward, PRVM_serverglobalvector(v_forward));
2663 VectorNegate(left, PRVM_serverglobalvector(v_right));
2664 VectorCopy(up, PRVM_serverglobalvector(v_up));
2665 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2666 model = SV_GetModelFromEdict(e);
2667 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2668 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2669 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2670 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2671 Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
2673 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2674 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2675 VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
2676 VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
2677 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2678 VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset));
2683 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2686 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2689 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2692 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2695 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2700 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2701 static void VM_SV_dropclient(prvm_prog_t *prog)
2704 client_t *oldhostclient;
2705 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2706 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2707 if (clientnum < 0 || clientnum >= svs.maxclients)
2709 VM_Warning(prog, "dropclient: not a client\n");
2712 if (!svs.clients[clientnum].active)
2714 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2717 oldhostclient = host_client;
2718 host_client = svs.clients + clientnum;
2719 SV_DropClient(false, "Client dropped");
2720 host_client = oldhostclient;
2723 //entity() spawnclient (DP_SV_BOTCLIENT)
2724 static void VM_SV_spawnclient(prvm_prog_t *prog)
2728 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2729 prog->xfunction->builtinsprofile += 2;
2731 for (i = 0;i < svs.maxclients;i++)
2733 if (!svs.clients[i].active)
2735 prog->xfunction->builtinsprofile += 100;
2736 SV_ConnectClient (i, NULL);
2737 // this has to be set or else ClientDisconnect won't be called
2738 // we assume the qc will call ClientConnect...
2739 svs.clients[i].clientconnectcalled = true;
2740 ed = PRVM_EDICT_NUM(i + 1);
2744 VM_RETURN_EDICT(ed);
2747 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2748 static void VM_SV_clienttype(prvm_prog_t *prog)
2751 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2752 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2753 if (clientnum < 0 || clientnum >= svs.maxclients)
2754 PRVM_G_FLOAT(OFS_RETURN) = 3; // CLIENTTYPE_NOTACLIENT
2755 else if (!svs.clients[clientnum].active)
2756 PRVM_G_FLOAT(OFS_RETURN) = 0; // CLIENTTYPE_DISCONNECTED
2757 else if (svs.clients[clientnum].netconnection)
2758 PRVM_G_FLOAT(OFS_RETURN) = 1; // CLIENTTYPE_REAL
2760 PRVM_G_FLOAT(OFS_RETURN) = 2; // CLIENTTYPE_BOT
2767 string(string key) serverkey
2770 static void VM_SV_serverkey(prvm_prog_t *prog)
2772 char string[VM_STRINGTEMP_LENGTH];
2773 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2774 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2775 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2778 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2779 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2784 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2786 e = PRVM_G_EDICT(OFS_PARM0);
2787 if (e == prog->edicts)
2789 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2794 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2797 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2798 if (i <= 0 || i >= MAX_MODELS)
2800 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2803 if (!sv.model_precache[i][0])
2805 VM_Warning(prog, "setmodelindex: model not precached\n");
2809 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2810 PRVM_serveredictfloat(e, modelindex) = i;
2812 mod = SV_GetModelByIndex(i);
2816 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2817 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2819 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2822 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2825 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2826 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2829 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2831 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2833 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2834 if (i <= 0 || i >= MAX_MODELS)
2836 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2839 if (!sv.model_precache[i][0])
2841 VM_Warning(prog, "modelnameforindex: model not precached\n");
2845 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2848 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2849 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2852 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2853 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2856 PRVM_G_FLOAT(OFS_RETURN) = i;
2859 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2860 static void VM_SV_trailparticles(prvm_prog_t *prog)
2863 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2865 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2868 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2869 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2870 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2871 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start);
2872 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end);
2873 MSG_WriteVector(&sv.datagram, start, sv.protocol);
2874 MSG_WriteVector(&sv.datagram, end, sv.protocol);
2875 SV_FlushBroadcastMessages();
2878 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2879 static void VM_SV_pointparticles(prvm_prog_t *prog)
2881 int effectnum, count;
2883 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2885 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2888 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2889 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2890 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2891 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2892 if (count == 1 && !VectorLength2(vel))
2895 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2896 MSG_WriteShort(&sv.datagram, effectnum);
2897 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2901 // 1+2+12+12+2=29 bytes
2902 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2903 MSG_WriteShort(&sv.datagram, effectnum);
2904 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2905 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2906 MSG_WriteShort(&sv.datagram, count);
2909 SV_FlushBroadcastMessages();
2912 qbool SV_VM_ConsoleCommand (const char *text)
2914 prvm_prog_t *prog = SVVM_prog;
2915 return PRVM_ConsoleCommand(prog, text, &prog->funcoffsets.ConsoleCmd, true, PRVM_EDICT_TO_PROG(sv.world.prog->edicts), sv.time, !(!sv.active || !prog || !prog->loaded), "QC function ConsoleCmd is missing");
2918 // #352 void(string cmdname) registercommand (EXT_CSQC)
2919 static void VM_SV_registercommand (prvm_prog_t *prog)
2921 VM_SAFEPARMCOUNT(1, VM_SV_registercmd);
2922 Cmd_AddCommand(CF_SERVER, PRVM_G_STRING(OFS_PARM0), NULL, "console command created by QuakeC");
2925 //PF_setpause, // void(float pause) setpause = #531;
2926 static void VM_SV_setpause(prvm_prog_t *prog) {
2928 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2929 if (pauseValue != 0) { //pause the game
2931 sv.pausedstart = host.realtime;
2932 } else { //disable pause, in case it was enabled
2933 if (sv.paused != 0) {
2938 // send notification to all clients
2939 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2940 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2943 // #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.
2944 static void VM_SV_skel_create(prvm_prog_t *prog)
2946 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2947 model_t *model = SV_GetModelByIndex(modelindex);
2948 skeleton_t *skeleton;
2950 PRVM_G_FLOAT(OFS_RETURN) = 0;
2951 if (!model || !model->num_bones)
2953 for (i = 0;i < MAX_EDICTS;i++)
2954 if (!prog->skeletons[i])
2956 if (i == MAX_EDICTS)
2958 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(prog->progs_mempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2959 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2960 skeleton->model = model;
2961 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2962 // initialize to identity matrices
2963 for (i = 0;i < skeleton->model->num_bones;i++)
2964 skeleton->relativetransforms[i] = identitymatrix;
2967 // #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
2968 static void VM_SV_skel_build(prvm_prog_t *prog)
2970 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2971 skeleton_t *skeleton;
2972 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2973 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2974 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2975 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2976 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2977 model_t *model = SV_GetModelByIndex(modelindex);
2981 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2982 frameblend_t frameblend[MAX_FRAMEBLENDS];
2983 matrix4x4_t bonematrix;
2985 PRVM_G_FLOAT(OFS_RETURN) = 0;
2986 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2988 firstbone = max(0, firstbone);
2989 lastbone = min(lastbone, model->num_bones - 1);
2990 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2991 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2992 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time);
2993 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2995 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2997 memset(&bonematrix, 0, sizeof(bonematrix));
2998 for (blendindex = 0;blendindex < numblends;blendindex++)
3000 Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
3001 Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp);
3003 Matrix4x4_Normalize3(&bonematrix, &bonematrix);
3004 Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac);
3006 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
3009 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3010 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
3012 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3013 skeleton_t *skeleton;
3014 PRVM_G_FLOAT(OFS_RETURN) = 0;
3015 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3017 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
3020 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
3021 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
3023 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3024 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3025 skeleton_t *skeleton;
3026 PRVM_G_INT(OFS_RETURN) = 0;
3027 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3029 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3031 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
3034 // #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)
3035 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
3037 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3038 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3039 skeleton_t *skeleton;
3040 PRVM_G_FLOAT(OFS_RETURN) = 0;
3041 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3043 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3045 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
3048 // #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
3049 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
3051 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3052 const char *tagname = PRVM_G_STRING(OFS_PARM1);
3053 skeleton_t *skeleton;
3054 PRVM_G_FLOAT(OFS_RETURN) = 0;
3055 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3057 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
3060 // #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)
3061 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
3063 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3064 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3065 skeleton_t *skeleton;
3067 vec3_t forward, left, up, origin;
3068 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3069 VectorClear(PRVM_clientglobalvector(v_forward));
3070 VectorClear(PRVM_clientglobalvector(v_right));
3071 VectorClear(PRVM_clientglobalvector(v_up));
3072 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3074 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3076 matrix = skeleton->relativetransforms[bonenum];
3077 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3078 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3079 VectorNegate(left, PRVM_clientglobalvector(v_right));
3080 VectorCopy(up, PRVM_clientglobalvector(v_up));
3081 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3084 // #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)
3085 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
3087 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3088 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3089 skeleton_t *skeleton;
3092 vec3_t forward, left, up, origin;
3093 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3094 VectorClear(PRVM_clientglobalvector(v_forward));
3095 VectorClear(PRVM_clientglobalvector(v_right));
3096 VectorClear(PRVM_clientglobalvector(v_up));
3097 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3099 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3101 matrix = skeleton->relativetransforms[bonenum];
3102 // convert to absolute
3103 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3106 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3108 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3109 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3110 VectorNegate(left, PRVM_clientglobalvector(v_right));
3111 VectorCopy(up, PRVM_clientglobalvector(v_up));
3112 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3115 // #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)
3116 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3118 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3119 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3120 vec3_t forward, left, up, origin;
3121 skeleton_t *skeleton;
3123 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3125 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3127 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3128 VectorNegate(PRVM_clientglobalvector(v_right), left);
3129 VectorCopy(PRVM_clientglobalvector(v_up), up);
3130 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3131 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3132 skeleton->relativetransforms[bonenum] = matrix;
3135 // #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)
3136 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3138 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3139 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3140 vec3_t forward, left, up, origin;
3141 skeleton_t *skeleton;
3144 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3146 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3148 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3149 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3150 VectorNegate(PRVM_clientglobalvector(v_right), left);
3151 VectorCopy(PRVM_clientglobalvector(v_up), up);
3152 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3153 temp = skeleton->relativetransforms[bonenum];
3154 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3157 // #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)
3158 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3160 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3161 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3162 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3164 vec3_t forward, left, up, origin;
3165 skeleton_t *skeleton;
3168 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3170 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3171 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3172 VectorNegate(PRVM_clientglobalvector(v_right), left);
3173 VectorCopy(PRVM_clientglobalvector(v_up), up);
3174 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3175 firstbone = max(0, firstbone);
3176 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3177 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3179 temp = skeleton->relativetransforms[bonenum];
3180 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3184 // #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
3185 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3187 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3188 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3189 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3190 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3192 skeleton_t *skeletondst;
3193 skeleton_t *skeletonsrc;
3194 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3196 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3198 firstbone = max(0, firstbone);
3199 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3200 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3201 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3202 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3205 // #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)
3206 static void VM_SV_skel_delete(prvm_prog_t *prog)
3208 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3209 skeleton_t *skeleton;
3210 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3213 prog->skeletons[skeletonindex] = NULL;
3216 // #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
3217 static void VM_SV_frameforname(prvm_prog_t *prog)
3219 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3220 model_t *model = SV_GetModelByIndex(modelindex);
3221 const char *name = PRVM_G_STRING(OFS_PARM1);
3223 PRVM_G_FLOAT(OFS_RETURN) = -1;
3224 if (!model || !model->animscenes)
3226 for (i = 0;i < model->numframes;i++)
3228 if (!strcasecmp(model->animscenes[i].name, name))
3230 PRVM_G_FLOAT(OFS_RETURN) = i;
3236 // #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.
3237 static void VM_SV_frameduration(prvm_prog_t *prog)
3239 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3240 model_t *model = SV_GetModelByIndex(modelindex);
3241 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3242 PRVM_G_FLOAT(OFS_RETURN) = 0;
3243 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3245 if (model->animscenes[framenum].framerate)
3246 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3250 prvm_builtin_t vm_sv_builtins[] = {
3251 NULL, // #0 NULL function (not callable) (QUAKE)
3252 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3253 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3254 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3255 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3256 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3257 VM_break, // #6 void() break (QUAKE)
3258 VM_random, // #7 float() random (QUAKE)
3259 VM_SV_sound, // #8 void(entity e, float chan, string samp, float volume[, float atten[, float pitchchange[, float flags]]]) sound (QUAKE)
3260 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3261 VM_error, // #10 void(string e) error (QUAKE)
3262 VM_objerror, // #11 void(string e) objerror (QUAKE)
3263 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3264 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3265 VM_spawn, // #14 entity() spawn (QUAKE)
3266 VM_remove, // #15 void(entity e) remove (QUAKE)
3267 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3268 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3269 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3270 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3271 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3272 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3273 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3274 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3275 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3276 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3277 VM_ftos, // #26 string(float f) ftos (QUAKE)
3278 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3279 VM_coredump, // #28 void() coredump (QUAKE)
3280 VM_traceon, // #29 void() traceon (QUAKE)
3281 VM_traceoff, // #30 void() traceoff (QUAKE)
3282 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3283 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3284 NULL, // #33 (QUAKE)
3285 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3286 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3287 VM_rint, // #36 float(float v) rint (QUAKE)
3288 VM_floor, // #37 float(float v) floor (QUAKE)
3289 VM_ceil, // #38 float(float v) ceil (QUAKE)
3290 NULL, // #39 (QUAKE)
3291 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3292 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3293 NULL, // #42 (QUAKE)
3294 VM_fabs, // #43 float(float f) fabs (QUAKE)
3295 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3296 VM_cvar, // #45 float(string s) cvar (QUAKE)
3297 VM_localcmd_server, // #46 void(string s) localcmd (QUAKE)
3298 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3299 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3300 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3301 NULL, // #50 (QUAKE)
3302 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3303 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3304 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3305 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3306 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3307 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3308 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3309 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3310 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3311 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3312 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3313 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3314 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3315 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3316 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3317 NULL, // #66 (QUAKE)
3318 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3319 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3320 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3321 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3322 NULL, // #71 (QUAKE)
3323 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3324 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3325 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3326 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3327 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3328 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3329 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3330 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3331 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3332 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3333 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3334 NULL, // #83 (QUAKE)
3335 NULL, // #84 (QUAKE)
3336 NULL, // #85 (QUAKE)
3337 NULL, // #86 (QUAKE)
3338 NULL, // #87 (QUAKE)
3339 NULL, // #88 (QUAKE)
3340 NULL, // #89 (QUAKE)
3341 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3342 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3343 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3344 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3345 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3346 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3347 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3348 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3349 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3350 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3351 // FrikaC and Telejano range #100-#199
3362 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3363 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3364 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3365 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3366 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3367 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3368 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3369 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3370 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3371 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3452 // FTEQW range #200-#299
3471 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3474 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3475 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3476 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3477 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3478 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3479 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3480 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3481 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3482 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3483 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3485 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3493 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3516 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.
3517 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
3518 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3519 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3520 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)
3521 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
3522 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)
3523 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)
3524 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)
3525 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)
3526 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)
3527 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
3528 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)
3529 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
3530 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.
3553 // CSQC range #300-#399
3554 NULL, // #300 void() clearscene (EXT_CSQC)
3555 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3556 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3557 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3558 NULL, // #304 void() renderscene (EXT_CSQC)
3559 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3560 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3561 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3562 NULL, // #308 void() R_EndPolygon
3564 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3565 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3569 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3570 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3571 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3572 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3573 NULL, // #319 void(string name) freepic (EXT_CSQC)
3574 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3575 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3576 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3577 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3578 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3579 NULL, // #325 void(void) drawresetcliparea
3584 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3585 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3586 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3587 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3588 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3589 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3590 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3591 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3592 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3593 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3594 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3595 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3596 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3597 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3598 NULL, // #344 vector() getmousepos (EXT_CSQC)
3599 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3600 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3601 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3602 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3603 NULL, // #349 float() isdemo (EXT_CSQC)
3604 VM_isserver, // #350 float() isserver (EXT_CSQC)
3605 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3606 VM_SV_registercommand, // #352 void(string cmdname) registercommand (EXT_CSQC)
3607 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3608 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3614 NULL, // #360 float() readbyte (EXT_CSQC)
3615 NULL, // #361 float() readchar (EXT_CSQC)
3616 NULL, // #362 float() readshort (EXT_CSQC)
3617 NULL, // #363 float() readlong (EXT_CSQC)
3618 NULL, // #364 float() readcoord (EXT_CSQC)
3619 NULL, // #365 float() readangle (EXT_CSQC)
3620 NULL, // #366 string() readstring (EXT_CSQC)
3621 NULL, // #367 float() readfloat (EXT_CSQC)
3654 // LadyHavoc's range #400-#499
3655 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3656 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3657 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3658 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3659 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3660 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3661 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3662 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3663 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)
3664 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3665 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3666 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3667 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3668 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3669 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3670 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3671 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3672 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3673 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3674 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3675 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3676 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3677 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3678 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3679 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3680 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3681 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3682 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3683 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3684 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3685 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3686 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3687 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3688 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3689 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3690 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3691 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3692 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3693 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3694 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3695 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3696 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3697 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3698 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3699 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3700 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3701 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3702 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3703 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3704 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3705 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3706 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3707 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3708 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3709 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3710 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3711 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3712 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3714 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3715 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3716 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3717 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3718 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3719 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3720 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3721 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3722 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3723 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3724 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3726 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3727 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3728 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3729 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3730 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3731 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3732 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3733 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3734 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3735 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3736 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3737 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3738 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3739 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3740 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3741 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3749 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3750 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3751 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3752 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3753 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3754 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3755 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3756 VM_SV_WritePicture, // #501
3758 VM_whichpack, // #503 string(string) whichpack = #503;
3765 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3766 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3767 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3768 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)
3769 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3770 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3771 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3772 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3773 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3774 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3784 VM_loadfromdata, // #529
3785 VM_loadfromfile, // #530
3786 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3788 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3789 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3790 VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP)
3791 VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP)
3792 VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP)
3793 VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP)
3795 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3796 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3797 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3821 VM_SV_findbox, // #566 entity(vector mins, vector maxs) findbox = #566; (DP_QC_FINDBOX)
3860 VM_callfunction, // #605
3861 VM_writetofile, // #606
3862 VM_isfunction, // #607
3868 VM_parseentitydata, // #613
3879 VM_SV_getextresponse, // #624 string getextresponse(void)
3882 VM_sprintf, // #627 string sprintf(string format, ...)
3883 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3884 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3894 VM_digest_hex, // #639
3897 VM_coverage, // #642
3901 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3903 void SVVM_init_cmd(prvm_prog_t *prog)
3908 void SVVM_reset_cmd(prvm_prog_t *prog)
3910 World_End(&sv.world);
3912 if(prog->loaded && PRVM_serverfunction(SV_Shutdown))
3914 func_t s = PRVM_serverfunction(SV_Shutdown);
3915 PRVM_serverglobalfloat(time) = sv.time;
3916 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3917 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");