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 SV_NudgeOutOfSolid(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 SV_NudgeOutOfSolid(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 || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1459 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1460 return &sv.reliable_datagram;
1463 return &svs.clients[entnum-1].netconnection->message;
1466 VM_Warning(prog, "WriteDest: bad destination\n");
1468 return &sv.reliable_datagram;
1474 return sv.writeentitiestoclient_msg;
1480 static void VM_SV_WriteByte(prvm_prog_t *prog)
1482 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1483 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1486 static void VM_SV_WriteChar(prvm_prog_t *prog)
1488 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1489 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1492 static void VM_SV_WriteShort(prvm_prog_t *prog)
1494 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1495 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1498 static void VM_SV_WriteLong(prvm_prog_t *prog)
1500 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1501 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1504 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1506 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1507 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1510 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1512 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1513 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1516 static void VM_SV_WriteString(prvm_prog_t *prog)
1518 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1519 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1522 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1524 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1525 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1529 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1531 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1532 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1535 // writes a picture as at most size bytes of data
1537 // IMGNAME \0 SIZE(short) IMGDATA
1538 // if failed to read/compress:
1540 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1541 static void VM_SV_WritePicture(prvm_prog_t *prog)
1543 const char *imgname;
1547 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1549 imgname = PRVM_G_STRING(OFS_PARM1);
1550 size = (size_t) PRVM_G_FLOAT(OFS_PARM2);
1554 MSG_WriteString(WriteDest(prog), imgname);
1555 if(Image_Compress(imgname, size, &buf, &size))
1558 MSG_WriteShort(WriteDest(prog), (int)size);
1559 SZ_Write(WriteDest(prog), (unsigned char *) buf, (int)size);
1564 MSG_WriteShort(WriteDest(prog), 0);
1568 //////////////////////////////////////////////////////////
1570 static void VM_SV_makestatic(prvm_prog_t *prog)
1575 // allow 0 parameters due to an id1 qc bug in which this function is used
1576 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1577 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1579 if (prog->argc >= 1)
1580 ent = PRVM_G_EDICT(OFS_PARM0);
1582 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1583 if (ent == prog->edicts)
1585 VM_Warning(prog, "makestatic: can not modify world entity\n");
1590 VM_Warning(prog, "makestatic: can not modify free entity\n");
1595 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1598 if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1600 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1601 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1602 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1606 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1607 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1608 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1612 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1613 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1614 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1617 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1618 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1619 for (i=0 ; i<3 ; i++)
1621 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1622 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1625 // throw the entity away now
1626 PRVM_ED_Free(prog, ent);
1629 //=============================================================================
1636 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1642 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1644 ent = PRVM_G_EDICT(OFS_PARM0);
1645 i = PRVM_NUM_FOR_EDICT(ent);
1646 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1648 Con_Print("tried to setspawnparms on a non-client\n");
1652 // copy spawn parms out of the client_t
1653 client = svs.clients + i-1;
1654 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1655 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1662 Returns a color vector indicating the lighting at the requested point.
1664 (Internal Operation note: actually measures the light beneath the point, just like
1665 the model lighting on the client)
1670 static void VM_SV_getlight(prvm_prog_t *prog)
1672 vec3_t ambientcolor, diffusecolor, diffusenormal;
1674 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1675 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
1676 VectorClear(ambientcolor);
1677 VectorClear(diffusecolor);
1678 VectorClear(diffusenormal);
1679 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1680 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1681 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1686 unsigned char type; // 1/2/8 or 0 to indicate unused
1690 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)
1691 static int vm_customstats_last;
1693 void VM_CustomStats_Clear (void)
1695 memset(vm_customstats, 0, sizeof(vm_customstats));
1696 vm_customstats_last = -1;
1699 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1701 prvm_prog_t *prog = SVVM_prog;
1709 for(i=MIN_VM_STAT; i<=vm_customstats_last ;i++)
1711 if(!vm_customstats[i].type)
1713 switch(vm_customstats[i].type)
1715 //string as 16 bytes
1718 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1719 stats[i] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1720 stats[i+1] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1721 stats[i+2] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1722 stats[i+3] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1724 //float field sent as-is
1726 // 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
1727 u.f = PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1730 //integer value of float field
1732 stats[i] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1740 extern cvar_t sv_gameplayfix_customstats;
1742 // void(float index, float type, .void field) SV_AddStat = #232;
1743 // Set up an auto-sent player stat.
1744 // Client's get thier own fields sent to them. Index may not be less than 32.
1745 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1746 // 1: string (4 stats carrying a total of 16 charactures)
1747 // 2: float (one stat, float converted to an integer for transportation)
1748 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1749 static void VM_SV_AddStat(prvm_prog_t *prog)
1753 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1755 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1756 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1757 off = PRVM_G_INT (OFS_PARM2);
1766 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);
1772 VM_Warning(prog, "PF_SV_AddStat: index (%i) may not be less than %i\n", i, MIN_VM_STAT);
1776 if (i >= MAX_CL_STATS)
1778 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);
1782 if (i > (MAX_CL_STATS - 4) && type == 1)
1784 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);
1788 // these are hazardous to override but sort of allowed if one wants to be adventurous... and enjoys warnings.
1789 if (i < MIN_VM_STAT)
1790 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);
1791 else if (i >= MAX_VM_STAT && !sv_gameplayfix_customstats.integer)
1792 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);
1793 else if (i > (MAX_VM_STAT - 4) && type == 1 && !sv_gameplayfix_customstats.integer)
1794 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);
1796 vm_customstats[i].type = type;
1797 vm_customstats[i].fieldoffset = off;
1798 if(vm_customstats_last < i)
1799 vm_customstats_last = i;
1806 copies data from one entity to another
1808 copyentity(src, dst)
1811 static void VM_SV_copyentity(prvm_prog_t *prog)
1813 prvm_edict_t *in, *out;
1814 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1815 in = PRVM_G_EDICT(OFS_PARM0);
1816 if (in == prog->edicts)
1818 VM_Warning(prog, "copyentity: can not read world entity\n");
1823 VM_Warning(prog, "copyentity: can not read free entity\n");
1826 out = PRVM_G_EDICT(OFS_PARM1);
1827 if (out == prog->edicts)
1829 VM_Warning(prog, "copyentity: can not modify world entity\n");
1834 VM_Warning(prog, "copyentity: can not modify free entity\n");
1837 memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
1847 sets the color of a client and broadcasts the update to all connected clients
1849 setcolor(clientent, value)
1852 static void VM_SV_setcolor(prvm_prog_t *prog)
1857 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1858 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1859 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1861 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1863 Con_Print("tried to setcolor a non-client\n");
1867 client = svs.clients + entnum-1;
1870 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1871 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1874 if (client->old_colors != client->colors)
1876 client->old_colors = client->colors;
1877 // send notification to all clients
1878 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1879 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1880 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1888 effect(origin, modelname, startframe, framecount, framerate)
1891 static void VM_SV_effect(prvm_prog_t *prog)
1896 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1897 s = PRVM_G_STRING(OFS_PARM1);
1900 VM_Warning(prog, "effect: no model specified\n");
1904 i = SV_ModelIndex(s, 1);
1907 VM_Warning(prog, "effect: model not precached\n");
1911 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1913 VM_Warning(prog, "effect: framecount < 1\n");
1917 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1919 VM_Warning(prog, "effect: framerate < 1\n");
1923 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1924 SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1927 static void VM_SV_te_blood(prvm_prog_t *prog)
1929 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1930 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1932 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1933 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1936 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1939 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1940 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1941 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1943 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1944 SV_FlushBroadcastMessages();
1947 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1949 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1950 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1952 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1953 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1955 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1965 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1966 SV_FlushBroadcastMessages();
1969 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1971 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1972 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1973 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1975 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1976 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1977 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1979 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1980 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1981 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1982 SV_FlushBroadcastMessages();
1985 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1987 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1988 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1990 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1991 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1993 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1994 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1995 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1997 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1998 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1999 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2001 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2002 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2005 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2007 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2008 // gravity true/false
2009 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
2011 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
2012 SV_FlushBroadcastMessages();
2015 static void VM_SV_te_particlerain(prvm_prog_t *prog)
2017 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
2018 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2020 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2021 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2023 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2024 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2025 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2028 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2029 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2031 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2032 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2033 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2035 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2037 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2038 SV_FlushBroadcastMessages();
2041 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
2043 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
2044 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2046 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2047 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2049 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2050 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2054 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2055 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2058 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2059 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2061 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2063 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2064 SV_FlushBroadcastMessages();
2067 static void VM_SV_te_spark(prvm_prog_t *prog)
2069 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
2070 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2072 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2073 MSG_WriteByte(&sv.datagram, TE_SPARK);
2075 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2076 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2077 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2079 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2080 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2081 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2083 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2084 SV_FlushBroadcastMessages();
2087 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2089 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2090 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2091 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2093 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2094 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2095 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2096 SV_FlushBroadcastMessages();
2099 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2101 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2102 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2103 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2105 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2106 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2107 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2108 SV_FlushBroadcastMessages();
2111 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2113 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2114 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2115 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2117 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2118 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2119 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2120 SV_FlushBroadcastMessages();
2123 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2125 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2126 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2127 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2129 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2130 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2131 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2132 SV_FlushBroadcastMessages();
2135 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2137 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2138 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2139 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2141 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2142 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2143 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2144 SV_FlushBroadcastMessages();
2147 static void VM_SV_te_customflash(prvm_prog_t *prog)
2149 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2150 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2152 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2153 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2155 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2156 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2157 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2159 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2161 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2163 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2164 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2165 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2166 SV_FlushBroadcastMessages();
2169 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2171 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2172 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2173 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2175 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2176 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2177 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2178 SV_FlushBroadcastMessages();
2181 static void VM_SV_te_spike(prvm_prog_t *prog)
2183 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2184 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2185 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2187 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2188 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2189 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2190 SV_FlushBroadcastMessages();
2193 static void VM_SV_te_superspike(prvm_prog_t *prog)
2195 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2196 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2197 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2199 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2200 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2201 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2202 SV_FlushBroadcastMessages();
2205 static void VM_SV_te_explosion(prvm_prog_t *prog)
2207 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2208 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2209 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2211 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2212 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2213 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2214 SV_FlushBroadcastMessages();
2217 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2219 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2220 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2221 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2223 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2224 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2225 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2226 SV_FlushBroadcastMessages();
2229 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2231 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2232 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2233 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2235 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2236 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2237 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2238 SV_FlushBroadcastMessages();
2241 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2243 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2244 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2245 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2247 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2248 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2249 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2250 SV_FlushBroadcastMessages();
2253 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2255 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2256 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2257 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2259 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2260 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2261 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2262 SV_FlushBroadcastMessages();
2265 static void VM_SV_te_teleport(prvm_prog_t *prog)
2267 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2268 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2269 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2271 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2272 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2273 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2274 SV_FlushBroadcastMessages();
2277 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2279 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2280 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2281 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2283 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2284 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2285 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2287 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2288 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2289 SV_FlushBroadcastMessages();
2292 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2294 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2295 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2296 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2298 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2300 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2301 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2302 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2304 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2305 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2306 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2307 SV_FlushBroadcastMessages();
2310 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2312 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2313 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2314 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2316 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2318 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2319 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2320 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2322 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2323 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2324 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2325 SV_FlushBroadcastMessages();
2328 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2330 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2331 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2332 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2334 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2336 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2337 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2338 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2340 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2341 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2342 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2343 SV_FlushBroadcastMessages();
2346 static void VM_SV_te_beam(prvm_prog_t *prog)
2348 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2349 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2350 MSG_WriteByte(&sv.datagram, TE_BEAM);
2352 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2354 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2355 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2356 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2358 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2359 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2360 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2361 SV_FlushBroadcastMessages();
2364 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2366 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2367 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2368 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2369 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2370 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2371 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2372 SV_FlushBroadcastMessages();
2375 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2377 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2378 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2379 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2381 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2382 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2383 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2385 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2386 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2387 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2389 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2390 SV_FlushBroadcastMessages();
2393 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2394 //this function originally written by KrimZon, made shorter by LadyHavoc
2395 static void VM_SV_clientcommand(prvm_prog_t *prog)
2397 client_t *temp_client;
2399 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2401 //find client for this entity
2402 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2403 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2405 Con_Print("PF_clientcommand: entity is not a client\n");
2409 temp_client = host_client;
2410 host_client = svs.clients + i;
2411 Cmd_ExecuteString(cmd_serverfromclient, PRVM_G_STRING(OFS_PARM1), src_client, true);
2412 host_client = temp_client;
2415 //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)
2416 static void VM_SV_setattachment(prvm_prog_t *prog)
2418 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2419 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2420 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2423 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2425 if (e == prog->edicts)
2427 VM_Warning(prog, "setattachment: can not modify world entity\n");
2432 VM_Warning(prog, "setattachment: can not modify free entity\n");
2436 if (tagentity == NULL)
2437 tagentity = prog->edicts;
2441 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2443 model = SV_GetModelFromEdict(tagentity);
2446 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2448 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);
2451 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));
2454 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2455 PRVM_serveredictfloat(e, tag_index) = tagindex;
2458 /////////////////////////////////////////
2459 // DP_MD3_TAGINFO extension coded by VorteX
2461 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2465 i = (int)PRVM_serveredictfloat(e, modelindex);
2466 if (i < 1 || i >= MAX_MODELS)
2469 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2472 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2479 Matrix4x4_CreateIdentity(tag_localmatrix);
2481 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2483 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2494 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qbool viewmatrix)
2497 float pitchsign = 1;
2499 scale = PRVM_serveredictfloat(ent, scale);
2504 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);
2507 pitchsign = SV_GetPitchSign(prog, ent);
2508 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);
2512 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2515 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2517 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2518 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2519 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2520 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2522 *out = identitymatrix;
2526 // Warnings/errors code:
2527 // 0 - normal (everything all-right)
2530 // 3 - null or non-precached model
2531 // 4 - no tags with requested index
2532 // 5 - runaway loop at attachment chain
2533 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2536 int modelindex, attachloop;
2537 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2540 *out = identitymatrix; // warnings and errors return identical matrix
2542 if (ent == prog->edicts)
2547 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2548 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2551 model = SV_GetModelByIndex(modelindex);
2553 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2554 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2555 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2557 tagmatrix = identitymatrix;
2558 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2562 if (attachloop >= 256) // prevent runaway looping
2564 // apply transformation by child's tagindex on parent entity and then
2565 // by parent entity itself
2566 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2567 if (ret && attachloop == 0)
2569 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2570 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2571 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2572 // next iteration we process the parent entity
2573 if (PRVM_serveredictedict(ent, tag_entity))
2575 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2576 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2583 // RENDER_VIEWMODEL magic
2584 if (PRVM_serveredictedict(ent, viewmodelforclient))
2586 Matrix4x4_Copy(&tagmatrix, out);
2587 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2589 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2590 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2595 //float(entity ent, string tagname) gettagindex;
2597 static void VM_SV_gettagindex(prvm_prog_t *prog)
2600 const char *tag_name;
2603 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2605 ent = PRVM_G_EDICT(OFS_PARM0);
2606 tag_name = PRVM_G_STRING(OFS_PARM1);
2608 if (ent == prog->edicts)
2610 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2615 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2620 if (!SV_GetModelFromEdict(ent))
2621 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2624 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2626 if(developer_extra.integer)
2627 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2629 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2632 //vector(entity ent, float tagindex) gettaginfo;
2633 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2637 matrix4x4_t tag_matrix;
2638 matrix4x4_t tag_localmatrix;
2640 const char *tagname;
2642 vec3_t forward, left, up, origin;
2643 const model_t *model;
2645 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2647 e = PRVM_G_EDICT(OFS_PARM0);
2648 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2650 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2651 Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
2652 VectorCopy(forward, PRVM_serverglobalvector(v_forward));
2653 VectorNegate(left, PRVM_serverglobalvector(v_right));
2654 VectorCopy(up, PRVM_serverglobalvector(v_up));
2655 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2656 model = SV_GetModelFromEdict(e);
2657 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2658 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2659 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2660 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2661 Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
2663 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2664 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2665 VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
2666 VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
2667 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2668 VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset));
2673 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2676 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2679 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2682 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2685 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2690 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2691 static void VM_SV_dropclient(prvm_prog_t *prog)
2694 client_t *oldhostclient;
2695 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2696 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2697 if (clientnum < 0 || clientnum >= svs.maxclients)
2699 VM_Warning(prog, "dropclient: not a client\n");
2702 if (!svs.clients[clientnum].active)
2704 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2707 oldhostclient = host_client;
2708 host_client = svs.clients + clientnum;
2709 SV_DropClient(false, "Client dropped");
2710 host_client = oldhostclient;
2713 //entity() spawnclient (DP_SV_BOTCLIENT)
2714 static void VM_SV_spawnclient(prvm_prog_t *prog)
2718 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2719 prog->xfunction->builtinsprofile += 2;
2721 for (i = 0;i < svs.maxclients;i++)
2723 if (!svs.clients[i].active)
2725 prog->xfunction->builtinsprofile += 100;
2726 SV_ConnectClient (i, NULL);
2727 // this has to be set or else ClientDisconnect won't be called
2728 // we assume the qc will call ClientConnect...
2729 svs.clients[i].clientconnectcalled = true;
2730 ed = PRVM_EDICT_NUM(i + 1);
2734 VM_RETURN_EDICT(ed);
2737 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2738 static void VM_SV_clienttype(prvm_prog_t *prog)
2741 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2742 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2743 if (clientnum < 0 || clientnum >= svs.maxclients)
2744 PRVM_G_FLOAT(OFS_RETURN) = 3;
2745 else if (!svs.clients[clientnum].active)
2746 PRVM_G_FLOAT(OFS_RETURN) = 0;
2747 else if (svs.clients[clientnum].netconnection)
2748 PRVM_G_FLOAT(OFS_RETURN) = 1;
2750 PRVM_G_FLOAT(OFS_RETURN) = 2;
2757 string(string key) serverkey
2760 static void VM_SV_serverkey(prvm_prog_t *prog)
2762 char string[VM_STRINGTEMP_LENGTH];
2763 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2764 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2765 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2768 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2769 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2774 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2776 e = PRVM_G_EDICT(OFS_PARM0);
2777 if (e == prog->edicts)
2779 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2784 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2787 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2788 if (i <= 0 || i >= MAX_MODELS)
2790 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2793 if (!sv.model_precache[i][0])
2795 VM_Warning(prog, "setmodelindex: model not precached\n");
2799 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2800 PRVM_serveredictfloat(e, modelindex) = i;
2802 mod = SV_GetModelByIndex(i);
2806 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2807 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2809 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2812 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2815 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2816 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2819 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2821 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2823 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2824 if (i <= 0 || i >= MAX_MODELS)
2826 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2829 if (!sv.model_precache[i][0])
2831 VM_Warning(prog, "modelnameforindex: model not precached\n");
2835 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2838 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2839 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2842 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2843 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2846 PRVM_G_FLOAT(OFS_RETURN) = i;
2849 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2850 static void VM_SV_trailparticles(prvm_prog_t *prog)
2853 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2855 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2858 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2859 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2860 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2861 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start);
2862 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end);
2863 MSG_WriteVector(&sv.datagram, start, sv.protocol);
2864 MSG_WriteVector(&sv.datagram, end, sv.protocol);
2865 SV_FlushBroadcastMessages();
2868 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2869 static void VM_SV_pointparticles(prvm_prog_t *prog)
2871 int effectnum, count;
2873 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2875 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2878 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2879 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2880 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2881 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2882 if (count == 1 && !VectorLength2(vel))
2885 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2886 MSG_WriteShort(&sv.datagram, effectnum);
2887 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2891 // 1+2+12+12+2=29 bytes
2892 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2893 MSG_WriteShort(&sv.datagram, effectnum);
2894 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2895 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2896 MSG_WriteShort(&sv.datagram, count);
2899 SV_FlushBroadcastMessages();
2902 qbool SV_VM_ConsoleCommand (const char *text)
2904 prvm_prog_t *prog = SVVM_prog;
2905 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");
2908 // #352 void(string cmdname) registercommand (EXT_CSQC)
2909 static void VM_SV_registercommand (prvm_prog_t *prog)
2911 VM_SAFEPARMCOUNT(1, VM_SV_registercmd);
2912 Cmd_AddCommand(CF_SERVER, PRVM_G_STRING(OFS_PARM0), NULL, "console command created by QuakeC");
2915 //PF_setpause, // void(float pause) setpause = #531;
2916 static void VM_SV_setpause(prvm_prog_t *prog) {
2918 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2919 if (pauseValue != 0) { //pause the game
2921 sv.pausedstart = host.realtime;
2922 } else { //disable pause, in case it was enabled
2923 if (sv.paused != 0) {
2928 // send notification to all clients
2929 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2930 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2933 // #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.
2934 static void VM_SV_skel_create(prvm_prog_t *prog)
2936 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2937 model_t *model = SV_GetModelByIndex(modelindex);
2938 skeleton_t *skeleton;
2940 PRVM_G_FLOAT(OFS_RETURN) = 0;
2941 if (!model || !model->num_bones)
2943 for (i = 0;i < MAX_EDICTS;i++)
2944 if (!prog->skeletons[i])
2946 if (i == MAX_EDICTS)
2948 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(prog->progs_mempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2949 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2950 skeleton->model = model;
2951 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2952 // initialize to identity matrices
2953 for (i = 0;i < skeleton->model->num_bones;i++)
2954 skeleton->relativetransforms[i] = identitymatrix;
2957 // #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
2958 static void VM_SV_skel_build(prvm_prog_t *prog)
2960 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2961 skeleton_t *skeleton;
2962 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2963 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2964 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2965 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2966 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2967 model_t *model = SV_GetModelByIndex(modelindex);
2971 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2972 frameblend_t frameblend[MAX_FRAMEBLENDS];
2973 matrix4x4_t bonematrix;
2975 PRVM_G_FLOAT(OFS_RETURN) = 0;
2976 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2978 firstbone = max(0, firstbone);
2979 lastbone = min(lastbone, model->num_bones - 1);
2980 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2981 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2982 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time);
2983 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2985 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2987 memset(&bonematrix, 0, sizeof(bonematrix));
2988 for (blendindex = 0;blendindex < numblends;blendindex++)
2990 Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2991 Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp);
2993 Matrix4x4_Normalize3(&bonematrix, &bonematrix);
2994 Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac);
2996 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2999 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3000 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
3002 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3003 skeleton_t *skeleton;
3004 PRVM_G_FLOAT(OFS_RETURN) = 0;
3005 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3007 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
3010 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
3011 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
3013 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3014 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3015 skeleton_t *skeleton;
3016 PRVM_G_INT(OFS_RETURN) = 0;
3017 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3019 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3021 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
3024 // #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)
3025 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
3027 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3028 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3029 skeleton_t *skeleton;
3030 PRVM_G_FLOAT(OFS_RETURN) = 0;
3031 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3033 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3035 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
3038 // #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
3039 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
3041 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3042 const char *tagname = PRVM_G_STRING(OFS_PARM1);
3043 skeleton_t *skeleton;
3044 PRVM_G_FLOAT(OFS_RETURN) = 0;
3045 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3047 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
3050 // #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)
3051 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
3053 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3054 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3055 skeleton_t *skeleton;
3057 vec3_t forward, left, up, origin;
3058 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3059 VectorClear(PRVM_clientglobalvector(v_forward));
3060 VectorClear(PRVM_clientglobalvector(v_right));
3061 VectorClear(PRVM_clientglobalvector(v_up));
3062 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3064 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3066 matrix = skeleton->relativetransforms[bonenum];
3067 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3068 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3069 VectorNegate(left, PRVM_clientglobalvector(v_right));
3070 VectorCopy(up, PRVM_clientglobalvector(v_up));
3071 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3074 // #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)
3075 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
3077 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3078 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3079 skeleton_t *skeleton;
3082 vec3_t forward, left, up, origin;
3083 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3084 VectorClear(PRVM_clientglobalvector(v_forward));
3085 VectorClear(PRVM_clientglobalvector(v_right));
3086 VectorClear(PRVM_clientglobalvector(v_up));
3087 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3089 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3091 matrix = skeleton->relativetransforms[bonenum];
3092 // convert to absolute
3093 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3096 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3098 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3099 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3100 VectorNegate(left, PRVM_clientglobalvector(v_right));
3101 VectorCopy(up, PRVM_clientglobalvector(v_up));
3102 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3105 // #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)
3106 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3108 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3109 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3110 vec3_t forward, left, up, origin;
3111 skeleton_t *skeleton;
3113 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3115 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3117 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3118 VectorNegate(PRVM_clientglobalvector(v_right), left);
3119 VectorCopy(PRVM_clientglobalvector(v_up), up);
3120 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3121 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3122 skeleton->relativetransforms[bonenum] = matrix;
3125 // #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)
3126 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3128 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3129 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3130 vec3_t forward, left, up, origin;
3131 skeleton_t *skeleton;
3134 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3136 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3138 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3139 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3140 VectorNegate(PRVM_clientglobalvector(v_right), left);
3141 VectorCopy(PRVM_clientglobalvector(v_up), up);
3142 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3143 temp = skeleton->relativetransforms[bonenum];
3144 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3147 // #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)
3148 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3150 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3151 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3152 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3154 vec3_t forward, left, up, origin;
3155 skeleton_t *skeleton;
3158 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3160 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3161 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3162 VectorNegate(PRVM_clientglobalvector(v_right), left);
3163 VectorCopy(PRVM_clientglobalvector(v_up), up);
3164 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3165 firstbone = max(0, firstbone);
3166 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3167 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3169 temp = skeleton->relativetransforms[bonenum];
3170 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3174 // #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
3175 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3177 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3178 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3179 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3180 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3182 skeleton_t *skeletondst;
3183 skeleton_t *skeletonsrc;
3184 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3186 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3188 firstbone = max(0, firstbone);
3189 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3190 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3191 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3192 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3195 // #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)
3196 static void VM_SV_skel_delete(prvm_prog_t *prog)
3198 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3199 skeleton_t *skeleton;
3200 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3203 prog->skeletons[skeletonindex] = NULL;
3206 // #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
3207 static void VM_SV_frameforname(prvm_prog_t *prog)
3209 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3210 model_t *model = SV_GetModelByIndex(modelindex);
3211 const char *name = PRVM_G_STRING(OFS_PARM1);
3213 PRVM_G_FLOAT(OFS_RETURN) = -1;
3214 if (!model || !model->animscenes)
3216 for (i = 0;i < model->numframes;i++)
3218 if (!strcasecmp(model->animscenes[i].name, name))
3220 PRVM_G_FLOAT(OFS_RETURN) = i;
3226 // #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.
3227 static void VM_SV_frameduration(prvm_prog_t *prog)
3229 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3230 model_t *model = SV_GetModelByIndex(modelindex);
3231 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3232 PRVM_G_FLOAT(OFS_RETURN) = 0;
3233 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3235 if (model->animscenes[framenum].framerate)
3236 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3240 prvm_builtin_t vm_sv_builtins[] = {
3241 NULL, // #0 NULL function (not callable) (QUAKE)
3242 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3243 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3244 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3245 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3246 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3247 VM_break, // #6 void() break (QUAKE)
3248 VM_random, // #7 float() random (QUAKE)
3249 VM_SV_sound, // #8 void(entity e, float chan, string samp, float volume[, float atten[, float pitchchange[, float flags]]]) sound (QUAKE)
3250 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3251 VM_error, // #10 void(string e) error (QUAKE)
3252 VM_objerror, // #11 void(string e) objerror (QUAKE)
3253 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3254 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3255 VM_spawn, // #14 entity() spawn (QUAKE)
3256 VM_remove, // #15 void(entity e) remove (QUAKE)
3257 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3258 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3259 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3260 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3261 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3262 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3263 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3264 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3265 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3266 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3267 VM_ftos, // #26 string(float f) ftos (QUAKE)
3268 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3269 VM_coredump, // #28 void() coredump (QUAKE)
3270 VM_traceon, // #29 void() traceon (QUAKE)
3271 VM_traceoff, // #30 void() traceoff (QUAKE)
3272 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3273 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3274 NULL, // #33 (QUAKE)
3275 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3276 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3277 VM_rint, // #36 float(float v) rint (QUAKE)
3278 VM_floor, // #37 float(float v) floor (QUAKE)
3279 VM_ceil, // #38 float(float v) ceil (QUAKE)
3280 NULL, // #39 (QUAKE)
3281 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3282 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3283 NULL, // #42 (QUAKE)
3284 VM_fabs, // #43 float(float f) fabs (QUAKE)
3285 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3286 VM_cvar, // #45 float(string s) cvar (QUAKE)
3287 VM_localcmd_server, // #46 void(string s) localcmd (QUAKE)
3288 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3289 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3290 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3291 NULL, // #50 (QUAKE)
3292 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3293 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3294 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3295 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3296 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3297 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3298 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3299 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3300 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3301 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3302 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3303 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3304 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3305 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3306 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3307 NULL, // #66 (QUAKE)
3308 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3309 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3310 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3311 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3312 NULL, // #71 (QUAKE)
3313 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3314 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3315 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3316 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3317 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3318 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3319 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3320 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3321 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3322 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3323 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3324 NULL, // #83 (QUAKE)
3325 NULL, // #84 (QUAKE)
3326 NULL, // #85 (QUAKE)
3327 NULL, // #86 (QUAKE)
3328 NULL, // #87 (QUAKE)
3329 NULL, // #88 (QUAKE)
3330 NULL, // #89 (QUAKE)
3331 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3332 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3333 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3334 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3335 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3336 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3337 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3338 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3339 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3340 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3341 // FrikaC and Telejano range #100-#199
3352 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3353 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3354 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3355 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3356 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3357 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3358 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3359 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3360 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3361 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3442 // FTEQW range #200-#299
3461 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3464 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3465 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3466 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3467 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3468 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3469 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3470 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3471 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3472 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3473 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3475 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3483 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3506 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.
3507 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
3508 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3509 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3510 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)
3511 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
3512 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)
3513 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)
3514 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)
3515 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)
3516 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)
3517 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
3518 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)
3519 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
3520 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.
3543 // CSQC range #300-#399
3544 NULL, // #300 void() clearscene (EXT_CSQC)
3545 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3546 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3547 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3548 NULL, // #304 void() renderscene (EXT_CSQC)
3549 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3550 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3551 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3552 NULL, // #308 void() R_EndPolygon
3554 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3555 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3559 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3560 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3561 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3562 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3563 NULL, // #319 void(string name) freepic (EXT_CSQC)
3564 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3565 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3566 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3567 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3568 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3569 NULL, // #325 void(void) drawresetcliparea
3574 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3575 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3576 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3577 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3578 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3579 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3580 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3581 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3582 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3583 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3584 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3585 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3586 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3587 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3588 NULL, // #344 vector() getmousepos (EXT_CSQC)
3589 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3590 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3591 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3592 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3593 NULL, // #349 float() isdemo (EXT_CSQC)
3594 VM_isserver, // #350 float() isserver (EXT_CSQC)
3595 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3596 VM_SV_registercommand, // #352 void(string cmdname) registercommand (EXT_CSQC)
3597 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3598 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3604 NULL, // #360 float() readbyte (EXT_CSQC)
3605 NULL, // #361 float() readchar (EXT_CSQC)
3606 NULL, // #362 float() readshort (EXT_CSQC)
3607 NULL, // #363 float() readlong (EXT_CSQC)
3608 NULL, // #364 float() readcoord (EXT_CSQC)
3609 NULL, // #365 float() readangle (EXT_CSQC)
3610 NULL, // #366 string() readstring (EXT_CSQC)
3611 NULL, // #367 float() readfloat (EXT_CSQC)
3644 // LadyHavoc's range #400-#499
3645 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3646 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3647 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3648 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3649 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3650 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3651 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3652 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3653 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)
3654 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3655 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3656 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3657 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3658 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3659 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3660 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3661 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3662 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3663 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3664 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3665 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3666 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3667 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3668 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3669 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3670 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3671 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3672 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3673 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3674 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3675 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3676 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3677 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3678 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3679 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3680 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3681 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3682 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3683 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3684 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3685 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3686 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3687 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3688 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3689 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3690 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3691 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3692 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3693 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3694 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3695 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3696 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3697 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3698 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3699 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3700 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3701 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3702 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3704 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3705 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3706 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3707 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3708 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3709 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3710 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3711 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3712 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3713 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3714 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3716 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3717 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3718 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3719 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3720 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3721 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3722 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3723 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3724 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3725 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3726 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3727 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3728 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3729 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3730 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3731 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3739 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3740 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3741 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3742 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3743 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3744 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3745 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3746 VM_SV_WritePicture, // #501
3748 VM_whichpack, // #503 string(string) whichpack = #503;
3755 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3756 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3757 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3758 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)
3759 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3760 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3761 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3762 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3763 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3764 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3774 VM_loadfromdata, // #529
3775 VM_loadfromfile, // #530
3776 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3778 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3779 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3780 VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP)
3781 VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP)
3782 VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP)
3783 VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP)
3785 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3786 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3787 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3811 VM_SV_findbox, // #566 entity(vector mins, vector maxs) findbox = #566; (DP_QC_FINDBOX)
3850 VM_callfunction, // #605
3851 VM_writetofile, // #606
3852 VM_isfunction, // #607
3858 VM_parseentitydata, // #613
3869 VM_SV_getextresponse, // #624 string getextresponse(void)
3872 VM_sprintf, // #627 string sprintf(string format, ...)
3873 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3874 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3884 VM_digest_hex, // #639
3887 VM_coverage, // #642
3891 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3893 void SVVM_init_cmd(prvm_prog_t *prog)
3898 void SVVM_reset_cmd(prvm_prog_t *prog)
3900 World_End(&sv.world);
3902 if(prog->loaded && PRVM_serverfunction(SV_Shutdown))
3904 func_t s = PRVM_serverfunction(SV_Shutdown);
3905 PRVM_serverglobalfloat(time) = sv.time;
3906 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3907 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");