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",
233 //"EXT_CSQC" // not ready yet
240 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.
242 setorigin (entity, origin)
245 static void VM_SV_setorigin(prvm_prog_t *prog)
249 VM_SAFEPARMCOUNT(2, VM_SV_setorigin);
251 e = PRVM_G_EDICT(OFS_PARM0);
252 if (e == prog->edicts)
254 VM_Warning(prog, "setorigin: can not modify world entity\n");
259 VM_Warning(prog, "setorigin: can not modify free entity\n");
262 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), PRVM_serveredictvector(e, origin));
263 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
264 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
268 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
269 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qbool rotate)
273 for (i=0 ; i<3 ; i++)
275 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
277 // set derived values
278 VectorCopy (min, PRVM_serveredictvector(e, mins));
279 VectorCopy (max, PRVM_serveredictvector(e, maxs));
280 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
289 the size box is rotated by the current angle
290 LadyHavoc: no it isn't...
292 setsize (entity, minvector, maxvector)
295 static void VM_SV_setsize(prvm_prog_t *prog)
300 VM_SAFEPARMCOUNT(3, VM_SV_setsize);
302 e = PRVM_G_EDICT(OFS_PARM0);
303 if (e == prog->edicts)
305 VM_Warning(prog, "setsize: can not modify world entity\n");
310 VM_Warning(prog, "setsize: can not modify free entity\n");
313 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), mins);
314 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), maxs);
315 SetMinMaxSize(prog, e, mins, maxs, false);
323 setmodel(entity, model)
326 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
327 static void VM_SV_setmodel(prvm_prog_t *prog)
333 VM_SAFEPARMCOUNT(2, VM_SV_setmodel);
335 e = PRVM_G_EDICT(OFS_PARM0);
336 if (e == prog->edicts)
338 VM_Warning(prog, "setmodel: can not modify world entity\n");
343 VM_Warning(prog, "setmodel: can not modify free entity\n");
346 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
347 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
348 PRVM_serveredictfloat(e, modelindex) = i;
350 mod = SV_GetModelByIndex(i);
354 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
355 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
357 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
360 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
367 single print to a specific client
369 sprint(clientent, value)
372 static void VM_SV_sprint(prvm_prog_t *prog)
376 char string[VM_STRINGTEMP_LENGTH];
378 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
380 VM_VarString(prog, 1, string, sizeof(string));
382 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
383 // LadyHavoc: div0 requested that sprintto world operate like print
390 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
392 VM_Warning(prog, "tried to centerprint to a non-client\n");
396 client = svs.clients + entnum-1;
397 if (!client->netconnection)
400 MSG_WriteChar(&client->netconnection->message,svc_print);
401 MSG_WriteString(&client->netconnection->message, string);
409 single print to a specific client
411 centerprint(clientent, value)
414 static void VM_SV_centerprint(prvm_prog_t *prog)
418 char string[VM_STRINGTEMP_LENGTH];
420 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
422 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
424 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
426 VM_Warning(prog, "tried to centerprint to a non-client\n");
430 client = svs.clients + entnum-1;
431 if (!client->netconnection)
434 VM_VarString(prog, 1, string, sizeof(string));
435 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
436 MSG_WriteString(&client->netconnection->message, string);
443 particle(origin, color, count)
446 static void VM_SV_particle(prvm_prog_t *prog)
452 VM_SAFEPARMCOUNT(4, VM_SV_particle);
454 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
455 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
456 color = (int)PRVM_G_FLOAT(OFS_PARM2);
457 count = (int)PRVM_G_FLOAT(OFS_PARM3);
458 SV_StartParticle (org, dir, color, count);
468 static void VM_SV_ambientsound(prvm_prog_t *prog)
472 prvm_vec_t vol, attenuation;
475 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
477 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
478 samp = PRVM_G_STRING(OFS_PARM1);
479 vol = PRVM_G_FLOAT(OFS_PARM2);
480 attenuation = PRVM_G_FLOAT(OFS_PARM3);
482 // check to see if samp was properly precached
483 soundnum = SV_SoundIndex(samp, 1);
491 if(sv.protocol == PROTOCOL_NEHAHRABJP)
494 // add an svc_spawnambient command to the level signon packet
497 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
499 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
501 MSG_WriteVector(&sv.signon, pos, sv.protocol);
503 if (large || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
504 MSG_WriteShort (&sv.signon, soundnum);
506 MSG_WriteByte (&sv.signon, soundnum);
508 MSG_WriteByte (&sv.signon, (int)(vol*255));
509 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
517 Each entity can have eight independant sound sources, like voice,
520 Channel 0 is an auto-allocate channel, the others override anything
521 already running on that entity/channel pair.
523 An attenuation of 0 will play full volume everywhere in the level.
524 Larger attenuations will drop off.
526 void(entity e, float chan, string samp, float volume[, float atten[, float pitchchange[, float flags]]]) sound (QUAKE)
529 static void VM_SV_sound(prvm_prog_t *prog)
533 prvm_edict_t *entity;
539 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
541 entity = PRVM_G_EDICT(OFS_PARM0);
542 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
543 sample = PRVM_G_STRING(OFS_PARM2);
544 nvolume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
547 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
551 attenuation = PRVM_G_FLOAT(OFS_PARM4);
555 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
560 if(channel >= 8 && channel <= 15) // weird QW feature
562 flags |= CHANNELFLAG_RELIABLE;
568 // LadyHavoc: we only let the qc set certain flags, others are off-limits
569 flags = (int)PRVM_G_FLOAT(OFS_PARM6) & (CHANNELFLAG_RELIABLE | CHANNELFLAG_FORCELOOP | CHANNELFLAG_PAUSED | CHANNELFLAG_FULLVOLUME);
572 if (nvolume < 0 || nvolume > 255)
574 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
578 if (attenuation < 0 || attenuation > 4)
580 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
584 channel = CHAN_USER2ENGINE(channel);
586 if (!IS_CHAN(channel))
588 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
592 SV_StartSound (entity, channel, sample, nvolume, attenuation, flags & CHANNELFLAG_RELIABLE, pitchchange);
599 Follows the same logic as VM_SV_sound, except instead of
600 an entity, an origin for the sound is provided, and channel
601 is omitted (since no entity is being tracked).
605 static void VM_SV_pointsound(prvm_prog_t *prog)
613 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
615 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
616 sample = PRVM_G_STRING(OFS_PARM1);
617 nvolume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
618 attenuation = PRVM_G_FLOAT(OFS_PARM3);
619 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
621 if (nvolume < 0 || nvolume > 255)
623 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
627 if (attenuation < 0 || attenuation > 4)
629 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
633 SV_StartPointSound (org, sample, nvolume, attenuation, pitchchange);
640 Used for use tracing and shot targeting
641 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
642 if the tryents flag is set.
644 traceline (vector1, vector2, movetype, ignore)
647 static void VM_SV_traceline(prvm_prog_t *prog)
654 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
656 prog->xfunction->builtinsprofile += 30;
658 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
659 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), v2);
660 move = (int)PRVM_G_FLOAT(OFS_PARM2);
661 ent = PRVM_G_EDICT(OFS_PARM3);
663 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]))
664 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));
666 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtracelinelength.value);
668 VM_SetTraceGlobals(prog, &trace);
676 Used for use tracing and shot targeting
677 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
678 if the tryents flag is set.
680 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
683 // LadyHavoc: added this for my own use, VERY useful, similar to traceline
684 static void VM_SV_tracebox(prvm_prog_t *prog)
686 vec3_t v1, v2, m1, m2;
691 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
693 prog->xfunction->builtinsprofile += 30;
695 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
696 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), m1);
697 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), m2);
698 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), v2);
699 move = (int)PRVM_G_FLOAT(OFS_PARM4);
700 ent = PRVM_G_EDICT(OFS_PARM5);
702 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]))
703 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));
705 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtraceboxlength.value);
707 VM_SetTraceGlobals(prog, &trace);
710 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
714 vec3_t move, end, tossentorigin, tossentmins, tossentmaxs;
715 vec3_t original_origin;
716 vec3_t original_velocity;
717 vec3_t original_angles;
718 vec3_t original_avelocity;
721 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
722 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
723 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
724 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
726 gravity = PRVM_serveredictfloat(tossent, gravity);
729 gravity *= sv_gravity.value * 0.025;
731 for (i = 0;i < 200;i++) // LadyHavoc: sanity check; never trace more than 10 seconds
733 SV_CheckVelocity (tossent);
734 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
735 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
736 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
737 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
738 VectorCopy(PRVM_serveredictvector(tossent, origin), tossentorigin);
739 VectorCopy(PRVM_serveredictvector(tossent, mins), tossentmins);
740 VectorCopy(PRVM_serveredictvector(tossent, maxs), tossentmaxs);
741 trace = SV_TraceBox(tossentorigin, tossentmins, tossentmaxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent), 0, 0, collision_extendmovelength.value);
742 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
743 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
745 if (trace.fraction < 1)
749 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
750 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
751 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
752 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
757 static void VM_SV_tracetoss(prvm_prog_t *prog)
761 prvm_edict_t *ignore;
763 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
765 prog->xfunction->builtinsprofile += 600;
767 ent = PRVM_G_EDICT(OFS_PARM0);
768 if (ent == prog->edicts)
770 VM_Warning(prog, "tracetoss: can not use world entity\n");
773 ignore = PRVM_G_EDICT(OFS_PARM1);
775 trace = SV_Trace_Toss(prog, ent, ignore);
777 VM_SetTraceGlobals(prog, &trace);
780 //============================================================================
782 static int checkpvsbytes;
783 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
785 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
791 // cycle to the next one
793 check = bound(1, check, svs.maxclients);
794 if (check == svs.maxclients)
802 prog->xfunction->builtinsprofile++;
804 if (i == svs.maxclients+1)
806 // look up the client's edict
807 ent = PRVM_EDICT_NUM(i);
808 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
809 if (i != check && (ent->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
811 // found a valid client (possibly the same one again)
815 // get the PVS for the entity
816 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
818 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
819 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
828 Returns a client (or object that has a client enemy) that would be a
831 If there is more than one valid option, they are cycled each frame
833 If (self.origin + self.viewofs) is not in the PVS of the current target,
834 it is not returned at all.
839 int c_invis, c_notvis;
840 static void VM_SV_checkclient(prvm_prog_t *prog)
842 prvm_edict_t *ent, *self;
845 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
847 // find a new check if on a new frame
848 if (sv.time - sv.lastchecktime >= 0.1)
850 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
851 sv.lastchecktime = sv.time;
854 // return check if it might be visible
855 ent = PRVM_EDICT_NUM(sv.lastcheck);
856 if (ent->free || PRVM_serveredictfloat(ent, health) <= 0)
858 VM_RETURN_EDICT(prog->edicts);
862 // if current entity can't possibly see the check entity, return 0
863 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
864 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
865 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
868 VM_RETURN_EDICT(prog->edicts);
872 // might be able to see it
874 VM_RETURN_EDICT(ent);
877 //============================================================================
883 Checks if an entity is in a point's PVS.
884 Should be fast but can be inexact.
886 float checkpvs(vector viewpos, entity viewee) = #240;
889 static void VM_SV_checkpvs(prvm_prog_t *prog)
891 vec3_t viewpos, absmin, absmax;
892 prvm_edict_t *viewee;
897 unsigned char fatpvs[MAX_MAP_LEAFS/8];
900 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
901 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
902 viewee = PRVM_G_EDICT(OFS_PARM1);
906 VM_Warning(prog, "checkpvs: can not check free entity\n");
907 PRVM_G_FLOAT(OFS_RETURN) = 4;
912 if(!sv.worldmodel || !sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
914 // no PVS support on this worldmodel... darn
915 PRVM_G_FLOAT(OFS_RETURN) = 3;
918 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
921 // viewpos isn't in any PVS... darn
922 PRVM_G_FLOAT(OFS_RETURN) = 2;
925 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
926 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
927 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, absmin, absmax);
929 // using fat PVS like FTEQW does (slow)
930 if(!sv.worldmodel || !sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
932 // no PVS support on this worldmodel... darn
933 PRVM_G_FLOAT(OFS_RETURN) = 3;
936 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
939 // viewpos isn't in any PVS... darn
940 PRVM_G_FLOAT(OFS_RETURN) = 2;
943 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
944 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
945 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, absmin, absmax);
954 Sends text over to the client's execution buffer
956 stuffcmd (clientent, value, ...)
959 static void VM_SV_stuffcmd(prvm_prog_t *prog)
963 char string[VM_STRINGTEMP_LENGTH];
965 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
967 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
968 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
970 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
974 VM_VarString(prog, 1, string, sizeof(string));
977 host_client = svs.clients + entnum-1;
978 SV_ClientCommands ("%s", string);
986 Returns a chain of entities that have origins within a spherical area
988 findradius (origin, radius)
991 static void VM_SV_findradius(prvm_prog_t *prog)
993 prvm_edict_t *ent, *chain;
994 vec_t radius, radius2;
995 vec3_t org, eorg, mins, maxs;
998 static prvm_edict_t *touchedicts[MAX_EDICTS];
1001 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
1004 chainfield = PRVM_G_INT(OFS_PARM2);
1006 chainfield = prog->fieldoffsets.chain;
1008 prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
1010 chain = (prvm_edict_t *)prog->edicts;
1012 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1013 radius = PRVM_G_FLOAT(OFS_PARM1);
1014 radius2 = radius * radius;
1016 mins[0] = org[0] - (radius + 1);
1017 mins[1] = org[1] - (radius + 1);
1018 mins[2] = org[2] - (radius + 1);
1019 maxs[0] = org[0] + (radius + 1);
1020 maxs[1] = org[1] + (radius + 1);
1021 maxs[2] = org[2] + (radius + 1);
1022 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1023 if (numtouchedicts > MAX_EDICTS)
1025 // this never happens
1026 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1027 numtouchedicts = MAX_EDICTS;
1029 for (i = 0;i < numtouchedicts;i++)
1031 ent = touchedicts[i];
1032 prog->xfunction->builtinsprofile++;
1033 // Quake did not return non-solid entities but darkplaces does
1034 // (note: this is the reason you can't blow up fallen zombies)
1035 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1037 // LadyHavoc: compare against bounding box rather than center so it
1038 // doesn't miss large objects, and use DotProduct instead of Length
1039 // for a major speedup
1040 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1041 if (sv_gameplayfix_findradiusdistancetobox.integer)
1043 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1044 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1045 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1048 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1049 if (DotProduct(eorg, eorg) < radius2)
1051 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1056 VM_RETURN_EDICT(chain);
1059 static void VM_SV_precache_sound(prvm_prog_t *prog)
1061 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1062 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1065 static void VM_SV_precache_model(prvm_prog_t *prog)
1067 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1068 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1069 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1076 float(float yaw, float dist[, settrace]) walkmove
1079 static void VM_SV_walkmove(prvm_prog_t *prog)
1088 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1090 // assume failure if it returns early
1091 PRVM_G_FLOAT(OFS_RETURN) = 0;
1093 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1094 if (ent == prog->edicts)
1096 VM_Warning(prog, "walkmove: can not modify world entity\n");
1101 VM_Warning(prog, "walkmove: can not modify free entity\n");
1104 yaw = PRVM_G_FLOAT(OFS_PARM0);
1105 dist = PRVM_G_FLOAT(OFS_PARM1);
1106 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1108 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1111 yaw = yaw*M_PI*2 / 360;
1113 move[0] = cos(yaw)*dist;
1114 move[1] = sin(yaw)*dist;
1117 // save program state, because SV_movestep may call other progs
1118 oldf = prog->xfunction;
1119 oldself = PRVM_serverglobaledict(self);
1121 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1124 // restore program state
1125 prog->xfunction = oldf;
1126 PRVM_serverglobaledict(self) = oldself;
1137 static void VM_SV_droptofloor(prvm_prog_t *prog)
1140 vec3_t end, entorigin, entmins, entmaxs;
1143 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1145 // assume failure if it returns early
1146 PRVM_G_FLOAT(OFS_RETURN) = 0;
1148 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1149 if (ent == prog->edicts)
1151 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1156 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1160 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1161 if (sv.worldmodel->brush.isq3bsp)
1163 else if (sv.worldmodel->brush.isq2bsp)
1166 end[2] -= 256; // Quake, QuakeWorld
1168 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1169 SV_NudgeOutOfSolid(ent);
1171 VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
1172 VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
1173 VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
1174 trace = SV_TraceBox(entorigin, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
1175 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1178 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]);
1179 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1180 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
1181 VectorSubtract(trace.endpos, offset, trace.endpos);
1182 if (trace.startsolid)
1184 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]);
1186 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1187 PRVM_serveredictedict(ent, groundentity) = 0;
1188 PRVM_G_FLOAT(OFS_RETURN) = 1;
1190 else if (trace.fraction < 1)
1192 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]);
1193 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1194 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1195 SV_NudgeOutOfSolid(ent);
1197 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1198 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1199 PRVM_G_FLOAT(OFS_RETURN) = 1;
1200 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1201 ent->priv.server->suspendedinairflag = true;
1206 if (!trace.allsolid && trace.fraction < 1)
1208 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1210 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1211 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1212 PRVM_G_FLOAT(OFS_RETURN) = 1;
1213 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1214 ent->priv.server->suspendedinairflag = true;
1223 void(float style, string value) lightstyle
1226 static void VM_SV_lightstyle(prvm_prog_t *prog)
1233 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1235 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1236 val = PRVM_G_STRING(OFS_PARM1);
1238 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1239 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1242 // change the string in sv
1243 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1245 // send message to all clients on this server
1246 if (sv.state != ss_active)
1249 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1251 if (client->active && client->netconnection)
1253 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1254 MSG_WriteChar (&client->netconnection->message,style);
1255 MSG_WriteString (&client->netconnection->message, val);
1265 static void VM_SV_checkbottom(prvm_prog_t *prog)
1267 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1268 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1276 static void VM_SV_pointcontents(prvm_prog_t *prog)
1279 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1280 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point);
1281 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(SV_PointSuperContents(point));
1288 Pick a vector for the player to shoot along
1289 vector aim(entity, missilespeed)
1292 static void VM_SV_aim(prvm_prog_t *prog)
1294 prvm_edict_t *ent, *check, *bestent;
1295 vec3_t start, dir, end, bestdir;
1298 float dist, bestdist;
1301 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1303 // assume failure if it returns early
1304 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1305 // if sv_aim is so high it can't possibly accept anything, skip out early
1306 if (sv_aim.value >= 1)
1309 ent = PRVM_G_EDICT(OFS_PARM0);
1310 if (ent == prog->edicts)
1312 VM_Warning(prog, "aim: can not use world entity\n");
1317 VM_Warning(prog, "aim: can not use free entity\n");
1320 //speed = PRVM_G_FLOAT(OFS_PARM1);
1322 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1325 // try sending a trace straight
1326 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1327 VectorMA (start, 2048, dir, end);
1328 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1329 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1330 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1332 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1337 // try all possible entities
1338 VectorCopy (dir, bestdir);
1339 bestdist = sv_aim.value;
1342 check = PRVM_NEXT_EDICT(prog->edicts);
1343 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1345 prog->xfunction->builtinsprofile++;
1346 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1350 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1351 continue; // don't aim at teammate
1352 for (j=0 ; j<3 ; j++)
1353 end[j] = PRVM_serveredictvector(check, origin)[j]
1354 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1355 VectorSubtract (end, start, dir);
1356 VectorNormalize (dir);
1357 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1358 if (dist < bestdist)
1359 continue; // to far to turn
1360 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1361 if (tr.ent == check)
1362 { // can shoot at this one
1370 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1371 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1372 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1374 VectorNormalize (end);
1375 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1379 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1384 ===============================================================================
1388 ===============================================================================
1391 #define MSG_BROADCAST 0 // unreliable to all
1392 #define MSG_ONE 1 // reliable to one (msg_entity)
1393 #define MSG_ALL 2 // reliable to all
1394 #define MSG_INIT 3 // write to the init string
1395 #define MSG_ENTITY 5
1397 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1403 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1407 return &sv.datagram;
1410 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1411 entnum = PRVM_NUM_FOR_EDICT(ent);
1412 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1414 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1415 return &sv.reliable_datagram;
1418 return &svs.clients[entnum-1].netconnection->message;
1421 VM_Warning(prog, "WriteDest: bad destination\n");
1423 return &sv.reliable_datagram;
1429 return sv.writeentitiestoclient_msg;
1435 static void VM_SV_WriteByte(prvm_prog_t *prog)
1437 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1438 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1441 static void VM_SV_WriteChar(prvm_prog_t *prog)
1443 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1444 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1447 static void VM_SV_WriteShort(prvm_prog_t *prog)
1449 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1450 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1453 static void VM_SV_WriteLong(prvm_prog_t *prog)
1455 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1456 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1459 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1461 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1462 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1465 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1467 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1468 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1471 static void VM_SV_WriteString(prvm_prog_t *prog)
1473 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1474 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1477 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1479 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1480 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1484 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1486 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1487 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1490 // writes a picture as at most size bytes of data
1492 // IMGNAME \0 SIZE(short) IMGDATA
1493 // if failed to read/compress:
1495 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1496 static void VM_SV_WritePicture(prvm_prog_t *prog)
1498 const char *imgname;
1502 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1504 imgname = PRVM_G_STRING(OFS_PARM1);
1505 size = (size_t) PRVM_G_FLOAT(OFS_PARM2);
1509 MSG_WriteString(WriteDest(prog), imgname);
1510 if(Image_Compress(imgname, size, &buf, &size))
1513 MSG_WriteShort(WriteDest(prog), (int)size);
1514 SZ_Write(WriteDest(prog), (unsigned char *) buf, (int)size);
1519 MSG_WriteShort(WriteDest(prog), 0);
1523 //////////////////////////////////////////////////////////
1525 static void VM_SV_makestatic(prvm_prog_t *prog)
1530 // allow 0 parameters due to an id1 qc bug in which this function is used
1531 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1532 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1534 if (prog->argc >= 1)
1535 ent = PRVM_G_EDICT(OFS_PARM0);
1537 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1538 if (ent == prog->edicts)
1540 VM_Warning(prog, "makestatic: can not modify world entity\n");
1545 VM_Warning(prog, "makestatic: can not modify free entity\n");
1550 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1553 if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1555 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1556 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1557 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1561 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1562 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1563 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1567 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1568 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1569 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1572 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1573 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1574 for (i=0 ; i<3 ; i++)
1576 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1577 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1580 // throw the entity away now
1581 PRVM_ED_Free(prog, ent);
1584 //=============================================================================
1591 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1597 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1599 ent = PRVM_G_EDICT(OFS_PARM0);
1600 i = PRVM_NUM_FOR_EDICT(ent);
1601 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1603 Con_Print("tried to setspawnparms on a non-client\n");
1607 // copy spawn parms out of the client_t
1608 client = svs.clients + i-1;
1609 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1610 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1617 Returns a color vector indicating the lighting at the requested point.
1619 (Internal Operation note: actually measures the light beneath the point, just like
1620 the model lighting on the client)
1625 static void VM_SV_getlight(prvm_prog_t *prog)
1627 vec3_t ambientcolor, diffusecolor, diffusenormal;
1629 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1630 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
1631 VectorClear(ambientcolor);
1632 VectorClear(diffusecolor);
1633 VectorClear(diffusenormal);
1634 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1635 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1636 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1641 unsigned char type; // 1/2/8 or 0 to indicate unused
1645 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)
1646 static int vm_customstats_last;
1648 void VM_CustomStats_Clear (void)
1650 memset(vm_customstats, 0, sizeof(vm_customstats));
1651 vm_customstats_last = -1;
1654 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1656 prvm_prog_t *prog = SVVM_prog;
1664 for(i=MIN_VM_STAT; i<=vm_customstats_last ;i++)
1666 if(!vm_customstats[i].type)
1668 switch(vm_customstats[i].type)
1670 //string as 16 bytes
1673 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1674 stats[i] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1675 stats[i+1] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1676 stats[i+2] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1677 stats[i+3] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1679 //float field sent as-is
1681 // 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
1682 u.f = PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1685 //integer value of float field
1687 stats[i] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1695 extern cvar_t sv_gameplayfix_customstats;
1697 // void(float index, float type, .void field) SV_AddStat = #232;
1698 // Set up an auto-sent player stat.
1699 // Client's get thier own fields sent to them. Index may not be less than 32.
1700 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1701 // 1: string (4 stats carrying a total of 16 charactures)
1702 // 2: float (one stat, float converted to an integer for transportation)
1703 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1704 static void VM_SV_AddStat(prvm_prog_t *prog)
1708 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1710 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1711 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1712 off = PRVM_G_INT (OFS_PARM2);
1721 VM_Warning(prog, "PF_SV_AddStat: unrecognized type %i - supported types are 1 (string up to 16 bytes, takes 4 stat slots), 2 (truncate to int32), 8 (send as float)", type);
1727 VM_Warning(prog, "PF_SV_AddStat: index (%i) may not be less than %i\n", i, MIN_VM_STAT);
1731 if (i >= MAX_CL_STATS)
1733 VM_Warning(prog, "PF_SV_AddStat: index (%i) >= MAX_CL_STATS (%i), not supported by protocol, and AddStat beyond MAX_VM_STAT (%i) conflicts with engine MOVEVARS\n", i, MAX_CL_STATS, MAX_VM_STAT);
1737 if (i > (MAX_CL_STATS - 4) && type == 1)
1739 VM_Warning(prog, "PF_SV_AddStat: index (%i) > (MAX_CL_STATS (%i) - 4) with string type won't fit in the protocol, and AddStat beyond MAX_VM_STAT conflicts with engine MOVEVARS\n", i, MAX_CL_STATS);
1743 // these are hazardous to override but sort of allowed if one wants to be adventurous... and enjoys warnings.
1744 if (i < MIN_VM_STAT)
1745 VM_Warning(prog, "PF_SV_AddStat: index (%i) < MIN_VM_STAT (%i) may conflict with engine stats - allowed, but this may break things\n", i, MIN_VM_STAT);
1746 else if (i >= MAX_VM_STAT && !sv_gameplayfix_customstats.integer)
1747 VM_Warning(prog, "PF_SV_AddStat: index (%i) >= MAX_VM_STAT (%i) conflicts with engine stats - allowed, but this may break slowmo and stuff\n", i, MAX_VM_STAT);
1748 else if (i > (MAX_VM_STAT - 4) && type == 1 && !sv_gameplayfix_customstats.integer)
1749 VM_Warning(prog, "PF_SV_AddStat: index (%i) >= MAX_VM_STAT (%i) - 4 with string type won't fit within MAX_VM_STAT, thus conflicting with engine stats - allowed, but this may break slowmo and stuff\n", i, MAX_VM_STAT);
1751 vm_customstats[i].type = type;
1752 vm_customstats[i].fieldoffset = off;
1753 if(vm_customstats_last < i)
1754 vm_customstats_last = i;
1761 copies data from one entity to another
1763 copyentity(src, dst)
1766 static void VM_SV_copyentity(prvm_prog_t *prog)
1768 prvm_edict_t *in, *out;
1769 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1770 in = PRVM_G_EDICT(OFS_PARM0);
1771 if (in == prog->edicts)
1773 VM_Warning(prog, "copyentity: can not read world entity\n");
1778 VM_Warning(prog, "copyentity: can not read free entity\n");
1781 out = PRVM_G_EDICT(OFS_PARM1);
1782 if (out == prog->edicts)
1784 VM_Warning(prog, "copyentity: can not modify world entity\n");
1789 VM_Warning(prog, "copyentity: can not modify free entity\n");
1792 memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
1802 sets the color of a client and broadcasts the update to all connected clients
1804 setcolor(clientent, value)
1807 static void VM_SV_setcolor(prvm_prog_t *prog)
1812 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1813 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1814 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1816 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1818 Con_Print("tried to setcolor a non-client\n");
1822 client = svs.clients + entnum-1;
1825 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1826 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1829 if (client->old_colors != client->colors)
1831 client->old_colors = client->colors;
1832 // send notification to all clients
1833 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1834 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1835 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1843 effect(origin, modelname, startframe, framecount, framerate)
1846 static void VM_SV_effect(prvm_prog_t *prog)
1851 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1852 s = PRVM_G_STRING(OFS_PARM1);
1855 VM_Warning(prog, "effect: no model specified\n");
1859 i = SV_ModelIndex(s, 1);
1862 VM_Warning(prog, "effect: model not precached\n");
1866 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1868 VM_Warning(prog, "effect: framecount < 1\n");
1872 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1874 VM_Warning(prog, "effect: framerate < 1\n");
1878 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1879 SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1882 static void VM_SV_te_blood(prvm_prog_t *prog)
1884 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1885 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1887 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1888 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1890 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1891 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1892 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1894 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1895 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1896 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1898 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1899 SV_FlushBroadcastMessages();
1902 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1904 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1905 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1907 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1908 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1911 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1912 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1914 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1915 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1916 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1918 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1920 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1921 SV_FlushBroadcastMessages();
1924 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1926 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1927 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1928 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1934 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1935 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1936 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1937 SV_FlushBroadcastMessages();
1940 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1942 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1943 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1945 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1946 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1948 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1949 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1950 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1952 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1953 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1954 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1960 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1962 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1963 // gravity true/false
1964 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1967 SV_FlushBroadcastMessages();
1970 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1972 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1973 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1975 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1976 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1978 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1979 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1980 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1983 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1984 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1990 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1992 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1993 SV_FlushBroadcastMessages();
1996 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1998 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1999 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2001 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2002 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2004 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2005 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2006 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2008 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2009 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2010 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2012 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2014 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2016 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2018 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2019 SV_FlushBroadcastMessages();
2022 static void VM_SV_te_spark(prvm_prog_t *prog)
2024 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
2025 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2027 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2028 MSG_WriteByte(&sv.datagram, TE_SPARK);
2030 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2031 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2032 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2034 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2035 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2036 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2038 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2039 SV_FlushBroadcastMessages();
2042 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2044 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2045 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2046 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2048 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2049 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2050 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2051 SV_FlushBroadcastMessages();
2054 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2056 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2057 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2058 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2060 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2061 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2062 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2063 SV_FlushBroadcastMessages();
2066 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2068 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2069 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2070 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2072 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2074 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2075 SV_FlushBroadcastMessages();
2078 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2080 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2081 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2082 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2084 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2085 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2086 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2087 SV_FlushBroadcastMessages();
2090 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2092 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2093 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2094 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2096 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2097 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2098 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2099 SV_FlushBroadcastMessages();
2102 static void VM_SV_te_customflash(prvm_prog_t *prog)
2104 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2105 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2107 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2108 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2110 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2111 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2112 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2114 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2116 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2118 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2119 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2120 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2121 SV_FlushBroadcastMessages();
2124 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2126 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2127 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2128 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2130 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2131 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2132 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2133 SV_FlushBroadcastMessages();
2136 static void VM_SV_te_spike(prvm_prog_t *prog)
2138 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2139 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2140 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2142 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2143 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2144 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2145 SV_FlushBroadcastMessages();
2148 static void VM_SV_te_superspike(prvm_prog_t *prog)
2150 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2151 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2152 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2154 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2155 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2156 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2157 SV_FlushBroadcastMessages();
2160 static void VM_SV_te_explosion(prvm_prog_t *prog)
2162 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2163 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2164 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2166 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2167 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2168 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2169 SV_FlushBroadcastMessages();
2172 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2174 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2175 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2176 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2178 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2179 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2180 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2181 SV_FlushBroadcastMessages();
2184 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2186 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2187 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2188 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2190 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2191 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2192 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2193 SV_FlushBroadcastMessages();
2196 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2198 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2199 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2200 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2202 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2203 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2204 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2205 SV_FlushBroadcastMessages();
2208 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2210 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2211 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2212 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2214 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2215 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2216 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2217 SV_FlushBroadcastMessages();
2220 static void VM_SV_te_teleport(prvm_prog_t *prog)
2222 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2223 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2224 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2226 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2227 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2229 SV_FlushBroadcastMessages();
2232 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2234 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2235 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2236 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2238 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2239 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2240 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2242 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2243 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2244 SV_FlushBroadcastMessages();
2247 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2249 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2250 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2251 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2253 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2255 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2256 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2257 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2259 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2260 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2261 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2262 SV_FlushBroadcastMessages();
2265 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2267 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2268 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2269 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2271 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2273 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2274 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2275 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2277 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2278 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2279 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2280 SV_FlushBroadcastMessages();
2283 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2285 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2286 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2287 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2289 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2291 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2292 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2293 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2295 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2296 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2297 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2298 SV_FlushBroadcastMessages();
2301 static void VM_SV_te_beam(prvm_prog_t *prog)
2303 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2304 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2305 MSG_WriteByte(&sv.datagram, TE_BEAM);
2307 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2309 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2310 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2311 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2313 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2314 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2315 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2316 SV_FlushBroadcastMessages();
2319 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2321 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2322 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2323 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2324 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2325 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2326 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2327 SV_FlushBroadcastMessages();
2330 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2332 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2333 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2334 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2336 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2337 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2338 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2340 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2341 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2342 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2344 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2345 SV_FlushBroadcastMessages();
2348 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2349 //this function originally written by KrimZon, made shorter by LadyHavoc
2350 static void VM_SV_clientcommand(prvm_prog_t *prog)
2352 client_t *temp_client;
2354 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2356 //find client for this entity
2357 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2358 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2360 Con_Print("PF_clientcommand: entity is not a client\n");
2364 temp_client = host_client;
2365 host_client = svs.clients + i;
2366 Cmd_ExecuteString(cmd_serverfromclient, PRVM_G_STRING(OFS_PARM1), src_client, true);
2367 host_client = temp_client;
2370 //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)
2371 static void VM_SV_setattachment(prvm_prog_t *prog)
2373 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2374 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2375 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2378 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2380 if (e == prog->edicts)
2382 VM_Warning(prog, "setattachment: can not modify world entity\n");
2387 VM_Warning(prog, "setattachment: can not modify free entity\n");
2391 if (tagentity == NULL)
2392 tagentity = prog->edicts;
2396 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2398 model = SV_GetModelFromEdict(tagentity);
2401 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2403 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);
2406 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));
2409 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2410 PRVM_serveredictfloat(e, tag_index) = tagindex;
2413 /////////////////////////////////////////
2414 // DP_MD3_TAGINFO extension coded by VorteX
2416 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2420 i = (int)PRVM_serveredictfloat(e, modelindex);
2421 if (i < 1 || i >= MAX_MODELS)
2424 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2427 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2434 Matrix4x4_CreateIdentity(tag_localmatrix);
2436 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2438 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2449 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qbool viewmatrix)
2452 float pitchsign = 1;
2454 scale = PRVM_serveredictfloat(ent, scale);
2459 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);
2462 pitchsign = SV_GetPitchSign(prog, ent);
2463 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);
2467 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2470 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2472 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2473 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2474 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2475 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2477 *out = identitymatrix;
2481 // Warnings/errors code:
2482 // 0 - normal (everything all-right)
2485 // 3 - null or non-precached model
2486 // 4 - no tags with requested index
2487 // 5 - runaway loop at attachment chain
2488 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2491 int modelindex, attachloop;
2492 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2495 *out = identitymatrix; // warnings and errors return identical matrix
2497 if (ent == prog->edicts)
2502 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2503 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2506 model = SV_GetModelByIndex(modelindex);
2508 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2509 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2510 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2512 tagmatrix = identitymatrix;
2513 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2517 if (attachloop >= 256) // prevent runaway looping
2519 // apply transformation by child's tagindex on parent entity and then
2520 // by parent entity itself
2521 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2522 if (ret && attachloop == 0)
2524 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2525 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2526 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2527 // next iteration we process the parent entity
2528 if (PRVM_serveredictedict(ent, tag_entity))
2530 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2531 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2538 // RENDER_VIEWMODEL magic
2539 if (PRVM_serveredictedict(ent, viewmodelforclient))
2541 Matrix4x4_Copy(&tagmatrix, out);
2542 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2544 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2545 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2550 //float(entity ent, string tagname) gettagindex;
2552 static void VM_SV_gettagindex(prvm_prog_t *prog)
2555 const char *tag_name;
2558 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2560 ent = PRVM_G_EDICT(OFS_PARM0);
2561 tag_name = PRVM_G_STRING(OFS_PARM1);
2563 if (ent == prog->edicts)
2565 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2570 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2575 if (!SV_GetModelFromEdict(ent))
2576 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2579 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2581 if(developer_extra.integer)
2582 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2584 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2587 //vector(entity ent, float tagindex) gettaginfo;
2588 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2592 matrix4x4_t tag_matrix;
2593 matrix4x4_t tag_localmatrix;
2595 const char *tagname;
2597 vec3_t forward, left, up, origin;
2598 const model_t *model;
2600 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2602 e = PRVM_G_EDICT(OFS_PARM0);
2603 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2605 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2606 Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
2607 VectorCopy(forward, PRVM_serverglobalvector(v_forward));
2608 VectorNegate(left, PRVM_serverglobalvector(v_right));
2609 VectorCopy(up, PRVM_serverglobalvector(v_up));
2610 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2611 model = SV_GetModelFromEdict(e);
2612 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2613 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2614 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2615 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2616 Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
2618 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2619 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2620 VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
2621 VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
2622 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2623 VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset));
2628 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2631 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2634 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2637 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2640 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2645 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2646 static void VM_SV_dropclient(prvm_prog_t *prog)
2649 client_t *oldhostclient;
2650 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2651 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2652 if (clientnum < 0 || clientnum >= svs.maxclients)
2654 VM_Warning(prog, "dropclient: not a client\n");
2657 if (!svs.clients[clientnum].active)
2659 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2662 oldhostclient = host_client;
2663 host_client = svs.clients + clientnum;
2664 SV_DropClient(false, "Client dropped");
2665 host_client = oldhostclient;
2668 //entity() spawnclient (DP_SV_BOTCLIENT)
2669 static void VM_SV_spawnclient(prvm_prog_t *prog)
2673 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2674 prog->xfunction->builtinsprofile += 2;
2676 for (i = 0;i < svs.maxclients;i++)
2678 if (!svs.clients[i].active)
2680 prog->xfunction->builtinsprofile += 100;
2681 SV_ConnectClient (i, NULL);
2682 // this has to be set or else ClientDisconnect won't be called
2683 // we assume the qc will call ClientConnect...
2684 svs.clients[i].clientconnectcalled = true;
2685 ed = PRVM_EDICT_NUM(i + 1);
2689 VM_RETURN_EDICT(ed);
2692 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2693 static void VM_SV_clienttype(prvm_prog_t *prog)
2696 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2697 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2698 if (clientnum < 0 || clientnum >= svs.maxclients)
2699 PRVM_G_FLOAT(OFS_RETURN) = 3;
2700 else if (!svs.clients[clientnum].active)
2701 PRVM_G_FLOAT(OFS_RETURN) = 0;
2702 else if (svs.clients[clientnum].netconnection)
2703 PRVM_G_FLOAT(OFS_RETURN) = 1;
2705 PRVM_G_FLOAT(OFS_RETURN) = 2;
2712 string(string key) serverkey
2715 static void VM_SV_serverkey(prvm_prog_t *prog)
2717 char string[VM_STRINGTEMP_LENGTH];
2718 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2719 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2720 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2723 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2724 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2729 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2731 e = PRVM_G_EDICT(OFS_PARM0);
2732 if (e == prog->edicts)
2734 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2739 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2742 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2743 if (i <= 0 || i >= MAX_MODELS)
2745 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2748 if (!sv.model_precache[i][0])
2750 VM_Warning(prog, "setmodelindex: model not precached\n");
2754 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2755 PRVM_serveredictfloat(e, modelindex) = i;
2757 mod = SV_GetModelByIndex(i);
2761 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2762 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2764 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2767 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2770 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2771 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2774 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2776 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2778 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2779 if (i <= 0 || i >= MAX_MODELS)
2781 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2784 if (!sv.model_precache[i][0])
2786 VM_Warning(prog, "modelnameforindex: model not precached\n");
2790 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2793 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2794 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2797 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2798 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2801 PRVM_G_FLOAT(OFS_RETURN) = i;
2804 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2805 static void VM_SV_trailparticles(prvm_prog_t *prog)
2808 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2810 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2813 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2814 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2815 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2816 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start);
2817 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end);
2818 MSG_WriteVector(&sv.datagram, start, sv.protocol);
2819 MSG_WriteVector(&sv.datagram, end, sv.protocol);
2820 SV_FlushBroadcastMessages();
2823 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2824 static void VM_SV_pointparticles(prvm_prog_t *prog)
2826 int effectnum, count;
2828 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2830 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2833 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2834 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2835 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2836 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2837 if (count == 1 && !VectorLength2(vel))
2840 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2841 MSG_WriteShort(&sv.datagram, effectnum);
2842 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2846 // 1+2+12+12+2=29 bytes
2847 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2848 MSG_WriteShort(&sv.datagram, effectnum);
2849 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2850 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2851 MSG_WriteShort(&sv.datagram, count);
2854 SV_FlushBroadcastMessages();
2857 qbool SV_VM_ConsoleCommand (const char *text)
2859 prvm_prog_t *prog = SVVM_prog;
2860 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");
2863 // #352 void(string cmdname) registercommand (EXT_CSQC)
2864 static void VM_SV_registercommand (prvm_prog_t *prog)
2866 VM_SAFEPARMCOUNT(1, VM_SV_registercmd);
2867 Cmd_AddCommand(CF_SERVER, PRVM_G_STRING(OFS_PARM0), NULL, "console command created by QuakeC");
2870 //PF_setpause, // void(float pause) setpause = #531;
2871 static void VM_SV_setpause(prvm_prog_t *prog) {
2873 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2874 if (pauseValue != 0) { //pause the game
2876 sv.pausedstart = host.realtime;
2877 } else { //disable pause, in case it was enabled
2878 if (sv.paused != 0) {
2883 // send notification to all clients
2884 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2885 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2888 // #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.
2889 static void VM_SV_skel_create(prvm_prog_t *prog)
2891 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2892 model_t *model = SV_GetModelByIndex(modelindex);
2893 skeleton_t *skeleton;
2895 PRVM_G_FLOAT(OFS_RETURN) = 0;
2896 if (!model || !model->num_bones)
2898 for (i = 0;i < MAX_EDICTS;i++)
2899 if (!prog->skeletons[i])
2901 if (i == MAX_EDICTS)
2903 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(prog->progs_mempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2904 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2905 skeleton->model = model;
2906 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2907 // initialize to identity matrices
2908 for (i = 0;i < skeleton->model->num_bones;i++)
2909 skeleton->relativetransforms[i] = identitymatrix;
2912 // #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
2913 static void VM_SV_skel_build(prvm_prog_t *prog)
2915 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2916 skeleton_t *skeleton;
2917 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2918 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2919 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2920 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2921 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2922 model_t *model = SV_GetModelByIndex(modelindex);
2926 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2927 frameblend_t frameblend[MAX_FRAMEBLENDS];
2928 matrix4x4_t bonematrix;
2930 PRVM_G_FLOAT(OFS_RETURN) = 0;
2931 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2933 firstbone = max(0, firstbone);
2934 lastbone = min(lastbone, model->num_bones - 1);
2935 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2936 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2937 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time);
2938 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2940 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2942 memset(&bonematrix, 0, sizeof(bonematrix));
2943 for (blendindex = 0;blendindex < numblends;blendindex++)
2945 Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2946 Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp);
2948 Matrix4x4_Normalize3(&bonematrix, &bonematrix);
2949 Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac);
2951 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2954 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2955 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
2957 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2958 skeleton_t *skeleton;
2959 PRVM_G_FLOAT(OFS_RETURN) = 0;
2960 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2962 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2965 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2966 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
2968 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2969 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2970 skeleton_t *skeleton;
2971 PRVM_G_INT(OFS_RETURN) = 0;
2972 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2974 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2976 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
2979 // #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)
2980 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
2982 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2983 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2984 skeleton_t *skeleton;
2985 PRVM_G_FLOAT(OFS_RETURN) = 0;
2986 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2988 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2990 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2993 // #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
2994 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
2996 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2997 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2998 skeleton_t *skeleton;
2999 PRVM_G_FLOAT(OFS_RETURN) = 0;
3000 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3002 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
3005 // #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)
3006 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
3008 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3009 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3010 skeleton_t *skeleton;
3012 vec3_t forward, left, up, origin;
3013 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3014 VectorClear(PRVM_clientglobalvector(v_forward));
3015 VectorClear(PRVM_clientglobalvector(v_right));
3016 VectorClear(PRVM_clientglobalvector(v_up));
3017 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3019 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3021 matrix = skeleton->relativetransforms[bonenum];
3022 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3023 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3024 VectorNegate(left, PRVM_clientglobalvector(v_right));
3025 VectorCopy(up, PRVM_clientglobalvector(v_up));
3026 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3029 // #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)
3030 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
3032 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3033 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3034 skeleton_t *skeleton;
3037 vec3_t forward, left, up, origin;
3038 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3039 VectorClear(PRVM_clientglobalvector(v_forward));
3040 VectorClear(PRVM_clientglobalvector(v_right));
3041 VectorClear(PRVM_clientglobalvector(v_up));
3042 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3044 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3046 matrix = skeleton->relativetransforms[bonenum];
3047 // convert to absolute
3048 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3051 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3053 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3054 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3055 VectorNegate(left, PRVM_clientglobalvector(v_right));
3056 VectorCopy(up, PRVM_clientglobalvector(v_up));
3057 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3060 // #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)
3061 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3063 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3064 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3065 vec3_t forward, left, up, origin;
3066 skeleton_t *skeleton;
3068 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3070 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3072 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3073 VectorNegate(PRVM_clientglobalvector(v_right), left);
3074 VectorCopy(PRVM_clientglobalvector(v_up), up);
3075 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3076 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3077 skeleton->relativetransforms[bonenum] = matrix;
3080 // #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)
3081 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3083 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3084 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3085 vec3_t forward, left, up, origin;
3086 skeleton_t *skeleton;
3089 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3091 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3093 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3094 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3095 VectorNegate(PRVM_clientglobalvector(v_right), left);
3096 VectorCopy(PRVM_clientglobalvector(v_up), up);
3097 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3098 temp = skeleton->relativetransforms[bonenum];
3099 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3102 // #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)
3103 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3105 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3106 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3107 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3109 vec3_t forward, left, up, origin;
3110 skeleton_t *skeleton;
3113 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3115 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3116 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3117 VectorNegate(PRVM_clientglobalvector(v_right), left);
3118 VectorCopy(PRVM_clientglobalvector(v_up), up);
3119 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3120 firstbone = max(0, firstbone);
3121 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3122 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3124 temp = skeleton->relativetransforms[bonenum];
3125 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3129 // #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
3130 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3132 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3133 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3134 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3135 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3137 skeleton_t *skeletondst;
3138 skeleton_t *skeletonsrc;
3139 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3141 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3143 firstbone = max(0, firstbone);
3144 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3145 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3146 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3147 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3150 // #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)
3151 static void VM_SV_skel_delete(prvm_prog_t *prog)
3153 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3154 skeleton_t *skeleton;
3155 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3158 prog->skeletons[skeletonindex] = NULL;
3161 // #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
3162 static void VM_SV_frameforname(prvm_prog_t *prog)
3164 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3165 model_t *model = SV_GetModelByIndex(modelindex);
3166 const char *name = PRVM_G_STRING(OFS_PARM1);
3168 PRVM_G_FLOAT(OFS_RETURN) = -1;
3169 if (!model || !model->animscenes)
3171 for (i = 0;i < model->numframes;i++)
3173 if (!strcasecmp(model->animscenes[i].name, name))
3175 PRVM_G_FLOAT(OFS_RETURN) = i;
3181 // #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.
3182 static void VM_SV_frameduration(prvm_prog_t *prog)
3184 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3185 model_t *model = SV_GetModelByIndex(modelindex);
3186 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3187 PRVM_G_FLOAT(OFS_RETURN) = 0;
3188 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3190 if (model->animscenes[framenum].framerate)
3191 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3195 prvm_builtin_t vm_sv_builtins[] = {
3196 NULL, // #0 NULL function (not callable) (QUAKE)
3197 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3198 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3199 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3200 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3201 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3202 VM_break, // #6 void() break (QUAKE)
3203 VM_random, // #7 float() random (QUAKE)
3204 VM_SV_sound, // #8 void(entity e, float chan, string samp, float volume[, float atten[, float pitchchange[, float flags]]]) sound (QUAKE)
3205 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3206 VM_error, // #10 void(string e) error (QUAKE)
3207 VM_objerror, // #11 void(string e) objerror (QUAKE)
3208 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3209 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3210 VM_spawn, // #14 entity() spawn (QUAKE)
3211 VM_remove, // #15 void(entity e) remove (QUAKE)
3212 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3213 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3214 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3215 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3216 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3217 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3218 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3219 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3220 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3221 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3222 VM_ftos, // #26 string(float f) ftos (QUAKE)
3223 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3224 VM_coredump, // #28 void() coredump (QUAKE)
3225 VM_traceon, // #29 void() traceon (QUAKE)
3226 VM_traceoff, // #30 void() traceoff (QUAKE)
3227 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3228 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3229 NULL, // #33 (QUAKE)
3230 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3231 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3232 VM_rint, // #36 float(float v) rint (QUAKE)
3233 VM_floor, // #37 float(float v) floor (QUAKE)
3234 VM_ceil, // #38 float(float v) ceil (QUAKE)
3235 NULL, // #39 (QUAKE)
3236 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3237 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3238 NULL, // #42 (QUAKE)
3239 VM_fabs, // #43 float(float f) fabs (QUAKE)
3240 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3241 VM_cvar, // #45 float(string s) cvar (QUAKE)
3242 VM_localcmd_server, // #46 void(string s) localcmd (QUAKE)
3243 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3244 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3245 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3246 NULL, // #50 (QUAKE)
3247 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3248 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3249 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3250 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3251 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3252 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3253 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3254 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3255 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3256 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3257 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3258 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3259 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3260 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3261 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3262 NULL, // #66 (QUAKE)
3263 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3264 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3265 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3266 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3267 NULL, // #71 (QUAKE)
3268 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3269 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3270 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3271 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3272 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3273 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3274 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3275 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3276 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3277 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3278 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3279 NULL, // #83 (QUAKE)
3280 NULL, // #84 (QUAKE)
3281 NULL, // #85 (QUAKE)
3282 NULL, // #86 (QUAKE)
3283 NULL, // #87 (QUAKE)
3284 NULL, // #88 (QUAKE)
3285 NULL, // #89 (QUAKE)
3286 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3287 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3288 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3289 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3290 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3291 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3292 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3293 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3294 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3295 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3296 // FrikaC and Telejano range #100-#199
3307 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3308 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3309 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3310 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3311 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3312 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3313 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3314 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3315 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3316 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3397 // FTEQW range #200-#299
3416 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3419 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3420 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3421 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3422 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3423 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3424 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3425 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3426 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3427 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3428 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3430 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3438 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3461 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.
3462 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
3463 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3464 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3465 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)
3466 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
3467 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)
3468 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)
3469 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)
3470 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)
3471 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)
3472 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
3473 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)
3474 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
3475 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.
3498 // CSQC range #300-#399
3499 NULL, // #300 void() clearscene (EXT_CSQC)
3500 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3501 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3502 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3503 NULL, // #304 void() renderscene (EXT_CSQC)
3504 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3505 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3506 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3507 NULL, // #308 void() R_EndPolygon
3509 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3510 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3514 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3515 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3516 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3517 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3518 NULL, // #319 void(string name) freepic (EXT_CSQC)
3519 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3520 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3521 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3522 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3523 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3524 NULL, // #325 void(void) drawresetcliparea
3529 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3530 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3531 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3532 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3533 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3534 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3535 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3536 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3537 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3538 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3539 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3540 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3541 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3542 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3543 NULL, // #344 vector() getmousepos (EXT_CSQC)
3544 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3545 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3546 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3547 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3548 NULL, // #349 float() isdemo (EXT_CSQC)
3549 VM_isserver, // #350 float() isserver (EXT_CSQC)
3550 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3551 VM_SV_registercommand, // #352 void(string cmdname) registercommand (EXT_CSQC)
3552 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3553 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3559 NULL, // #360 float() readbyte (EXT_CSQC)
3560 NULL, // #361 float() readchar (EXT_CSQC)
3561 NULL, // #362 float() readshort (EXT_CSQC)
3562 NULL, // #363 float() readlong (EXT_CSQC)
3563 NULL, // #364 float() readcoord (EXT_CSQC)
3564 NULL, // #365 float() readangle (EXT_CSQC)
3565 NULL, // #366 string() readstring (EXT_CSQC)
3566 NULL, // #367 float() readfloat (EXT_CSQC)
3599 // LadyHavoc's range #400-#499
3600 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3601 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3602 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3603 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3604 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3605 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3606 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3607 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3608 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)
3609 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3610 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3611 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3612 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3613 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3614 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3615 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3616 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3617 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3618 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3619 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3620 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3621 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3622 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3623 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3624 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3625 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3626 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3627 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3628 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3629 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3630 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3631 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3632 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3633 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3634 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3635 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3636 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3637 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3638 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3639 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3640 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3641 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3642 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3643 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3644 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3645 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3646 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3647 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3648 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3649 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3650 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3651 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3652 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3653 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3654 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3655 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3656 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3657 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3659 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3660 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3661 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3662 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3663 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3664 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3665 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3666 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3667 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3668 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3669 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3671 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3672 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3673 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3674 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3675 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3676 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3677 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3678 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3679 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3680 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3681 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3682 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3683 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3684 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3685 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3686 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3694 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3695 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3696 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3697 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3698 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3699 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3700 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3701 VM_SV_WritePicture, // #501
3703 VM_whichpack, // #503 string(string) whichpack = #503;
3710 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3711 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3712 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3713 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)
3714 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3715 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3716 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3717 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3718 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3719 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3729 VM_loadfromdata, // #529
3730 VM_loadfromfile, // #530
3731 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3733 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3734 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3735 VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP)
3736 VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP)
3737 VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP)
3738 VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP)
3740 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3741 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3742 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3805 VM_callfunction, // #605
3806 VM_writetofile, // #606
3807 VM_isfunction, // #607
3813 VM_parseentitydata, // #613
3824 VM_SV_getextresponse, // #624 string getextresponse(void)
3827 VM_sprintf, // #627 string sprintf(string format, ...)
3828 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3829 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3839 VM_digest_hex, // #639
3842 VM_coverage, // #642
3846 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3848 void SVVM_init_cmd(prvm_prog_t *prog)
3853 void SVVM_reset_cmd(prvm_prog_t *prog)
3855 World_End(&sv.world);
3857 if(prog->loaded && PRVM_serverfunction(SV_Shutdown))
3859 func_t s = PRVM_serverfunction(SV_Shutdown);
3860 PRVM_serverglobalfloat(time) = sv.time;
3861 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3862 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");