7 //============================================================================
12 const char *vm_sv_extensions[] = {
17 "DP_CON_ALIASPARAMETERS",
26 "DP_CSQC_ENTITYWORLDOBJECT",
27 "DP_CSQC_ENTITYMODELLIGHT",
28 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET",
30 "DP_CSQC_MINFPS_QUALITY",
31 "DP_CSQC_MULTIFRAME_INTERPOLATION",
32 "DP_CSQC_BOXPARTICLES",
33 "DP_CSQC_SPAWNPARTICLE",
34 "DP_CSQC_QUERYRENDERENTITY",
35 "DP_CSQC_ROTATEMOVES",
37 "DP_CSQC_V_CALCREFDEF_WIP1",
38 "DP_CSQC_V_CALCREFDEF_WIP2",
42 "DP_EF_DYNAMICMODELLIGHT",
51 "DP_EF_RESTARTANIM_BIT",
56 "DP_ENT_CUSTOMCOLORMAP",
57 "DP_ENT_EXTERIORMODELTOCLIENT",
60 "DP_ENT_LOWPRECISION",
62 "DP_ENT_TRAILEFFECTNUM",
64 "DP_GFX_EXTERNALTEXTURES",
65 "DP_GFX_EXTERNALTEXTURES_PERMAP",
67 "DP_GFX_MODEL_INTERPOLATION",
68 "DP_GFX_QUAKE3MODELTAGS",
72 "DP_GFX_FONTS_FREETYPE",
74 "DP_FONT_VARIABLEWIDTH",
76 "DP_HALFLIFE_MAP_CVAR",
79 "DP_LIGHTSTYLE_STATICVALUE",
83 "DP_MOVETYPEBOUNCEMISSILE",
84 "DP_MOVETYPEFLYWORLDONLY",
87 "DP_QC_ASINACOSATANATAN2TAN",
93 "DP_QC_CVAR_DEFSTRING",
94 "DP_QC_CVAR_DESCRIPTION",
98 "DP_QC_DIGEST_SHA256",
101 "DP_QC_ENTITYSTRING",
103 "DP_QC_EXTRESPONSEPACKET",
105 "DP_QC_FINDCHAINFLAGS",
106 "DP_QC_FINDCHAINFLOAT",
107 "DP_QC_FINDCHAIN_TOFIELD",
113 "DP_QC_GETSURFACETRIANGLE",
114 "DP_QC_GETSURFACEPOINTATTRIBUTE",
116 "DP_QC_GETTAGINFO_BONEPROPERTIES",
118 "DP_QC_GETTIME_CDTRACK",
122 "DP_QC_MULTIPLETEMPSTRINGS",
123 "DP_QC_NUM_FOR_EDICT",
125 "DP_QC_SINCOSSQRTPOW",
128 "DP_QC_STRINGBUFFERS",
129 "DP_QC_STRINGBUFFERS_CVARLIST",
130 "DP_QC_STRINGBUFFERS_EXT_WIP",
131 "DP_QC_STRINGCOLORFUNCTIONS",
132 "DP_QC_STRING_CASE_FUNCTIONS",
134 "DP_QC_TOKENIZEBYSEPARATOR",
135 "DP_QC_TOKENIZE_CONSOLE",
138 "DP_QC_TRACE_MOVETYPE_HITMODEL",
139 "DP_QC_TRACE_MOVETYPE_WORLDONLY",
140 "DP_QC_UNLIMITEDTEMPSTRINGS",
144 "DP_QC_VECTOANGLES_WITH_ROLL",
145 "DP_QC_VECTORVECTORS",
152 "DP_SKELETONOBJECTS",
153 "DP_SND_DIRECTIONLESSATTNNONE",
155 "DP_SND_SOUND7_WIP1",
156 "DP_SND_SOUND7_WIP2",
160 "DP_SND_GETSOUNDTIME",
162 "DP_VIDEO_SUBTITLES",
166 "DP_SV_BOUNCEFACTOR",
167 "DP_SV_CLIENTCAMERA",
168 "DP_SV_CLIENTCOLORS",
171 "DP_SV_CUSTOMIZEENTITYFORCLIENT",
172 "DP_SV_DISABLECLIENTPREDICTION",
173 "DP_SV_DISCARDABLEDEMO",
174 "DP_SV_DRAWONLYTOCLIENT",
177 "DP_SV_ENTITYCONTENTSTRANSITION",
178 "DP_SV_MODELFLAGS_AS_EFFECTS",
179 "DP_SV_MOVETYPESTEP_LANDEVENT",
181 "DP_SV_NODRAWTOCLIENT",
182 "DP_SV_ONENTITYNOSPAWNFUNCTION",
183 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION",
185 "DP_SV_PING_PACKETLOSS",
186 "DP_SV_PLAYERPHYSICS",
188 "DP_SV_POINTPARTICLES",
190 "DP_SV_PRECACHEANYTIME",
194 "DP_SV_ROTATINGBMODEL",
198 "DP_SV_SPAWNFUNC_PREFIX",
199 "DP_SV_WRITEPICTURE",
200 "DP_SV_WRITEUNTERMINATEDSTRING",
204 "DP_TE_EXPLOSIONRGB",
206 "DP_TE_PARTICLECUBE",
207 "DP_TE_PARTICLERAIN",
208 "DP_TE_PARTICLESNOW",
210 "DP_TE_QUADEFFECTS1",
213 "DP_TE_STANDARDEFFECTBUILTINS",
214 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO"
219 "FTE_CSQC_SKELETONOBJECTS",
222 "KRIMZON_SV_PARSECLIENTCOMMAND",
225 "NEXUIZ_PLAYERMODEL",
227 "PRYDON_CLIENTCURSOR",
228 "TENEBRAE_GFX_DLIGHTS",
234 "DP_QC_FS_SEARCH_PACKFILE",
236 //"EXT_CSQC" // not ready yet
243 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.
245 setorigin (entity, origin)
248 static void VM_SV_setorigin(prvm_prog_t *prog)
252 VM_SAFEPARMCOUNT(2, VM_SV_setorigin);
254 e = PRVM_G_EDICT(OFS_PARM0);
255 if (e == prog->edicts)
257 VM_Warning(prog, "setorigin: can not modify world entity\n");
260 if (e->priv.server->free)
262 VM_Warning(prog, "setorigin: can not modify free entity\n");
265 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), PRVM_serveredictvector(e, origin));
266 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
267 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
271 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
272 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qboolean rotate)
276 for (i=0 ; i<3 ; i++)
278 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
280 // set derived values
281 VectorCopy (min, PRVM_serveredictvector(e, mins));
282 VectorCopy (max, PRVM_serveredictvector(e, maxs));
283 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
292 the size box is rotated by the current angle
293 LadyHavoc: no it isn't...
295 setsize (entity, minvector, maxvector)
298 static void VM_SV_setsize(prvm_prog_t *prog)
303 VM_SAFEPARMCOUNT(3, VM_SV_setsize);
305 e = PRVM_G_EDICT(OFS_PARM0);
306 if (e == prog->edicts)
308 VM_Warning(prog, "setsize: can not modify world entity\n");
311 if (e->priv.server->free)
313 VM_Warning(prog, "setsize: can not modify free entity\n");
316 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), mins);
317 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), maxs);
318 SetMinMaxSize(prog, e, mins, maxs, false);
326 setmodel(entity, model)
329 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
330 static void VM_SV_setmodel(prvm_prog_t *prog)
336 VM_SAFEPARMCOUNT(2, VM_SV_setmodel);
338 e = PRVM_G_EDICT(OFS_PARM0);
339 if (e == prog->edicts)
341 VM_Warning(prog, "setmodel: can not modify world entity\n");
344 if (e->priv.server->free)
346 VM_Warning(prog, "setmodel: can not modify free entity\n");
349 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
350 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
351 PRVM_serveredictfloat(e, modelindex) = i;
353 mod = SV_GetModelByIndex(i);
357 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
358 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
360 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
363 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
370 single print to a specific client
372 sprint(clientent, value)
375 static void VM_SV_sprint(prvm_prog_t *prog)
379 char string[VM_STRINGTEMP_LENGTH];
381 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
383 VM_VarString(prog, 1, string, sizeof(string));
385 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
386 // LadyHavoc: div0 requested that sprintto world operate like print
393 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
395 VM_Warning(prog, "tried to centerprint to a non-client\n");
399 client = svs.clients + entnum-1;
400 if (!client->netconnection)
403 MSG_WriteChar(&client->netconnection->message,svc_print);
404 MSG_WriteString(&client->netconnection->message, string);
412 single print to a specific client
414 centerprint(clientent, value)
417 static void VM_SV_centerprint(prvm_prog_t *prog)
421 char string[VM_STRINGTEMP_LENGTH];
423 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
425 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
427 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
429 VM_Warning(prog, "tried to centerprint to a non-client\n");
433 client = svs.clients + entnum-1;
434 if (!client->netconnection)
437 VM_VarString(prog, 1, string, sizeof(string));
438 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
439 MSG_WriteString(&client->netconnection->message, string);
446 particle(origin, color, count)
449 static void VM_SV_particle(prvm_prog_t *prog)
455 VM_SAFEPARMCOUNT(4, VM_SV_particle);
457 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
458 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
459 color = (int)PRVM_G_FLOAT(OFS_PARM2);
460 count = (int)PRVM_G_FLOAT(OFS_PARM3);
461 SV_StartParticle (org, dir, color, count);
471 static void VM_SV_ambientsound(prvm_prog_t *prog)
475 prvm_vec_t vol, attenuation;
478 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
480 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
481 samp = PRVM_G_STRING(OFS_PARM1);
482 vol = PRVM_G_FLOAT(OFS_PARM2);
483 attenuation = PRVM_G_FLOAT(OFS_PARM3);
485 // check to see if samp was properly precached
486 soundnum = SV_SoundIndex(samp, 1);
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_NEHAHRABJP || 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->priv.server->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->priv.server->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);
904 if(viewee->priv.server->free)
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");
1099 if (ent->priv.server->free)
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;
1133 float(float yaw, float dist[, settrace]) walkmovedist (EXT_WRATH)
1136 static void VM_SV_walkmovedist(prvm_prog_t *prog)
1140 vec3_t move, oldorg, neworg;
1145 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmovedist);
1147 // assume failure if it returns early
1148 PRVM_G_FLOAT(OFS_RETURN) = 0;
1150 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1151 if (ent == prog->edicts)
1153 VM_Warning(prog, "walkmove: can not modify world entity\n");
1156 if (ent->priv.server->free)
1158 VM_Warning(prog, "walkmove: can not modify free entity\n");
1161 yaw = PRVM_G_FLOAT(OFS_PARM0);
1162 dist = PRVM_G_FLOAT(OFS_PARM1);
1163 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1165 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1168 yaw = yaw*M_PI*2 / 360;
1170 move[0] = cos(yaw)*dist;
1171 move[1] = sin(yaw)*dist;
1174 // save origin before move
1175 VectorCopy (PRVM_serveredictvector(ent, origin), oldorg);
1177 // save program state, because SV_movestep may call other progs
1178 oldf = prog->xfunction;
1179 oldself = PRVM_serverglobaledict(self);
1181 SV_movestep(ent, move, true, false, settrace);
1183 // restore program state
1184 prog->xfunction = oldf;
1185 PRVM_serverglobaledict(self) = oldself;
1187 // save origin after move
1188 VectorCopy (PRVM_serveredictvector(ent, origin), neworg);
1190 // return distance traveled
1191 PRVM_G_FLOAT(OFS_RETURN) = VectorDistance(oldorg, neworg);
1202 static void VM_SV_droptofloor(prvm_prog_t *prog)
1205 vec3_t end, entorigin, entmins, entmaxs;
1208 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1210 // assume failure if it returns early
1211 PRVM_G_FLOAT(OFS_RETURN) = 0;
1213 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1214 if (ent == prog->edicts)
1216 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1219 if (ent->priv.server->free)
1221 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1225 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1228 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1229 SV_NudgeOutOfSolid(ent);
1231 VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
1232 VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
1233 VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
1234 trace = SV_TraceBox(entorigin, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
1235 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1238 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]);
1239 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1240 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
1241 VectorSubtract(trace.endpos, offset, trace.endpos);
1242 if (trace.startsolid)
1244 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]);
1246 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1247 PRVM_serveredictedict(ent, groundentity) = 0;
1248 PRVM_G_FLOAT(OFS_RETURN) = 1;
1250 else if (trace.fraction < 1)
1252 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]);
1253 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1254 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1255 SV_NudgeOutOfSolid(ent);
1257 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1258 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1259 PRVM_G_FLOAT(OFS_RETURN) = 1;
1260 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1261 ent->priv.server->suspendedinairflag = true;
1266 if (!trace.allsolid && trace.fraction < 1)
1268 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1270 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1271 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1272 PRVM_G_FLOAT(OFS_RETURN) = 1;
1273 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1274 ent->priv.server->suspendedinairflag = true;
1283 void(float style, string value) lightstyle
1286 static void VM_SV_lightstyle(prvm_prog_t *prog)
1293 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1295 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1296 val = PRVM_G_STRING(OFS_PARM1);
1298 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1299 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1302 // change the string in sv
1303 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1305 // send message to all clients on this server
1306 if (sv.state != ss_active)
1309 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1311 if (client->active && client->netconnection)
1313 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1314 MSG_WriteChar (&client->netconnection->message,style);
1315 MSG_WriteString (&client->netconnection->message, val);
1325 static void VM_SV_checkbottom(prvm_prog_t *prog)
1327 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1328 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1336 static void VM_SV_pointcontents(prvm_prog_t *prog)
1339 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1340 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point);
1341 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(SV_PointSuperContents(point));
1348 Pick a vector for the player to shoot along
1349 vector aim(entity, missilespeed)
1352 static void VM_SV_aim(prvm_prog_t *prog)
1354 prvm_edict_t *ent, *check, *bestent;
1355 vec3_t start, dir, end, bestdir;
1358 float dist, bestdist;
1361 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1363 // assume failure if it returns early
1364 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1365 // if sv_aim is so high it can't possibly accept anything, skip out early
1366 if (sv_aim.value >= 1)
1369 ent = PRVM_G_EDICT(OFS_PARM0);
1370 if (ent == prog->edicts)
1372 VM_Warning(prog, "aim: can not use world entity\n");
1375 if (ent->priv.server->free)
1377 VM_Warning(prog, "aim: can not use free entity\n");
1380 //speed = PRVM_G_FLOAT(OFS_PARM1);
1382 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1385 // try sending a trace straight
1386 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1387 VectorMA (start, 2048, dir, end);
1388 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1389 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1390 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1392 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1397 // try all possible entities
1398 VectorCopy (dir, bestdir);
1399 bestdist = sv_aim.value;
1402 check = PRVM_NEXT_EDICT(prog->edicts);
1403 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1405 prog->xfunction->builtinsprofile++;
1406 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1410 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1411 continue; // don't aim at teammate
1412 for (j=0 ; j<3 ; j++)
1413 end[j] = PRVM_serveredictvector(check, origin)[j]
1414 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1415 VectorSubtract (end, start, dir);
1416 VectorNormalize (dir);
1417 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1418 if (dist < bestdist)
1419 continue; // to far to turn
1420 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1421 if (tr.ent == check)
1422 { // can shoot at this one
1430 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1431 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1432 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1434 VectorNormalize (end);
1435 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1439 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1444 ===============================================================================
1448 ===============================================================================
1451 #define MSG_BROADCAST 0 // unreliable to all
1452 #define MSG_ONE 1 // reliable to one (msg_entity)
1453 #define MSG_ALL 2 // reliable to all
1454 #define MSG_INIT 3 // write to the init string
1455 #define MSG_ENTITY 5
1457 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1463 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1467 return &sv.datagram;
1470 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1471 entnum = PRVM_NUM_FOR_EDICT(ent);
1472 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1474 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1475 return &sv.reliable_datagram;
1478 return &svs.clients[entnum-1].netconnection->message;
1481 VM_Warning(prog, "WriteDest: bad destination\n");
1483 return &sv.reliable_datagram;
1489 return sv.writeentitiestoclient_msg;
1495 static void VM_SV_WriteByte(prvm_prog_t *prog)
1497 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1498 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1501 static void VM_SV_WriteChar(prvm_prog_t *prog)
1503 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1504 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1507 static void VM_SV_WriteShort(prvm_prog_t *prog)
1509 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1510 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1513 static void VM_SV_WriteLong(prvm_prog_t *prog)
1515 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1516 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1519 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1521 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1522 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1525 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1527 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1528 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1531 static void VM_SV_WriteString(prvm_prog_t *prog)
1533 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1534 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1537 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1539 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1540 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1544 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1546 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1547 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1550 // writes a picture as at most size bytes of data
1552 // IMGNAME \0 SIZE(short) IMGDATA
1553 // if failed to read/compress:
1555 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1556 static void VM_SV_WritePicture(prvm_prog_t *prog)
1558 const char *imgname;
1562 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1564 imgname = PRVM_G_STRING(OFS_PARM1);
1565 size = (size_t) PRVM_G_FLOAT(OFS_PARM2);
1569 MSG_WriteString(WriteDest(prog), imgname);
1570 if(Image_Compress(imgname, size, &buf, &size))
1573 MSG_WriteShort(WriteDest(prog), (int)size);
1574 SZ_Write(WriteDest(prog), (unsigned char *) buf, (int)size);
1579 MSG_WriteShort(WriteDest(prog), 0);
1583 //////////////////////////////////////////////////////////
1585 static void VM_SV_makestatic(prvm_prog_t *prog)
1590 // allow 0 parameters due to an id1 qc bug in which this function is used
1591 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1592 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1594 if (prog->argc >= 1)
1595 ent = PRVM_G_EDICT(OFS_PARM0);
1597 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1598 if (ent == prog->edicts)
1600 VM_Warning(prog, "makestatic: can not modify world entity\n");
1603 if (ent->priv.server->free)
1605 VM_Warning(prog, "makestatic: can not modify free entity\n");
1610 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1615 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1616 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1617 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1619 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1621 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1622 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1623 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1627 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1628 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1629 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1632 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1633 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1634 for (i=0 ; i<3 ; i++)
1636 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1637 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1640 // throw the entity away now
1641 PRVM_ED_Free(prog, ent);
1644 //=============================================================================
1651 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1657 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1659 ent = PRVM_G_EDICT(OFS_PARM0);
1660 i = PRVM_NUM_FOR_EDICT(ent);
1661 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1663 Con_Print("tried to setspawnparms on a non-client\n");
1667 // copy spawn parms out of the client_t
1668 client = svs.clients + i-1;
1669 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1670 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1677 Returns a color vector indicating the lighting at the requested point.
1679 (Internal Operation note: actually measures the light beneath the point, just like
1680 the model lighting on the client)
1685 static void VM_SV_getlight(prvm_prog_t *prog)
1687 vec3_t ambientcolor, diffusecolor, diffusenormal;
1689 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1690 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
1691 VectorClear(ambientcolor);
1692 VectorClear(diffusecolor);
1693 VectorClear(diffusenormal);
1694 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1695 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1696 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1701 unsigned char type; // 1/2/8 or 0 to indicate unused
1705 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)
1706 static int vm_customstats_last;
1708 void VM_CustomStats_Clear (void)
1710 memset(vm_customstats, 0, sizeof(vm_customstats));
1711 vm_customstats_last = -1;
1714 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1716 prvm_prog_t *prog = SVVM_prog;
1724 for(i=MIN_VM_STAT; i<=vm_customstats_last ;i++)
1726 if(!vm_customstats[i].type)
1728 switch(vm_customstats[i].type)
1730 //string as 16 bytes
1733 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1734 stats[i] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1735 stats[i+1] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1736 stats[i+2] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1737 stats[i+3] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1739 //float field sent as-is
1741 // 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
1742 u.f = PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1745 //integer value of float field
1747 stats[i] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1755 extern cvar_t sv_gameplayfix_customstats;
1757 // void(float index, float type, .void field) SV_AddStat = #232;
1758 // Set up an auto-sent player stat.
1759 // Client's get thier own fields sent to them. Index may not be less than 32.
1760 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1761 // 1: string (4 stats carrying a total of 16 charactures)
1762 // 2: float (one stat, float converted to an integer for transportation)
1763 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1764 static void VM_SV_AddStat(prvm_prog_t *prog)
1768 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1770 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1771 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1772 off = PRVM_G_INT (OFS_PARM2);
1781 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);
1787 VM_Warning(prog, "PF_SV_AddStat: index (%i) may not be less than %i\n", i, MIN_VM_STAT);
1791 if (i >= MAX_CL_STATS)
1793 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);
1797 if (i > (MAX_CL_STATS - 4) && type == 1)
1799 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);
1803 // these are hazardous to override but sort of allowed if one wants to be adventurous... and enjoys warnings.
1804 if (i < MIN_VM_STAT)
1805 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);
1806 else if (i >= MAX_VM_STAT && !sv_gameplayfix_customstats.integer)
1807 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);
1808 else if (i > (MAX_VM_STAT - 4) && type == 1 && !sv_gameplayfix_customstats.integer)
1809 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);
1811 vm_customstats[i].type = type;
1812 vm_customstats[i].fieldoffset = off;
1813 if(vm_customstats_last < i)
1814 vm_customstats_last = i;
1821 copies data from one entity to another
1823 copyentity(src, dst)
1826 static void VM_SV_copyentity(prvm_prog_t *prog)
1828 prvm_edict_t *in, *out;
1829 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1830 in = PRVM_G_EDICT(OFS_PARM0);
1831 if (in == prog->edicts)
1833 VM_Warning(prog, "copyentity: can not read world entity\n");
1836 if (in->priv.server->free)
1838 VM_Warning(prog, "copyentity: can not read free entity\n");
1841 out = PRVM_G_EDICT(OFS_PARM1);
1842 if (out == prog->edicts)
1844 VM_Warning(prog, "copyentity: can not modify world entity\n");
1847 if (out->priv.server->free)
1849 VM_Warning(prog, "copyentity: can not modify free entity\n");
1852 memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
1853 if (VectorCompare(PRVM_serveredictvector(out, absmin), PRVM_serveredictvector(out, absmax)))
1863 sets the color of a client and broadcasts the update to all connected clients
1865 setcolor(clientent, value)
1868 static void VM_SV_setcolor(prvm_prog_t *prog)
1873 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1874 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1875 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1877 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1879 Con_Print("tried to setcolor a non-client\n");
1883 client = svs.clients + entnum-1;
1886 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1887 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1890 if (client->old_colors != client->colors)
1892 client->old_colors = client->colors;
1893 // send notification to all clients
1894 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1895 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1896 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1904 effect(origin, modelname, startframe, framecount, framerate)
1907 static void VM_SV_effect(prvm_prog_t *prog)
1912 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1913 s = PRVM_G_STRING(OFS_PARM1);
1916 VM_Warning(prog, "effect: no model specified\n");
1920 i = SV_ModelIndex(s, 1);
1923 VM_Warning(prog, "effect: model not precached\n");
1927 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1929 VM_Warning(prog, "effect: framecount < 1\n");
1933 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1935 VM_Warning(prog, "effect: framerate < 1\n");
1939 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1940 SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1943 static void VM_SV_te_blood(prvm_prog_t *prog)
1945 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1946 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1948 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1949 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1952 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1953 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1955 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1956 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1957 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1959 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1960 SV_FlushBroadcastMessages();
1963 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1965 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1966 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1968 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1969 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1972 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1973 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1975 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1976 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1977 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1979 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1981 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1982 SV_FlushBroadcastMessages();
1985 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1987 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1988 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1989 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1991 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1992 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1993 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1995 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1996 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1997 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1998 SV_FlushBroadcastMessages();
2001 static void VM_SV_te_particlecube(prvm_prog_t *prog)
2003 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
2004 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2006 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2007 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2009 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2010 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2011 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2014 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2015 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2017 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2018 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2019 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2021 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2023 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2024 // gravity true/false
2025 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
2028 SV_FlushBroadcastMessages();
2031 static void VM_SV_te_particlerain(prvm_prog_t *prog)
2033 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
2034 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2036 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2037 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2039 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2040 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2041 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2043 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2044 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2045 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2047 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2048 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2049 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2051 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2053 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2054 SV_FlushBroadcastMessages();
2057 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
2059 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
2060 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2062 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2063 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2065 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2066 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2067 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2069 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2070 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2071 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2074 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2075 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2077 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2079 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2080 SV_FlushBroadcastMessages();
2083 static void VM_SV_te_spark(prvm_prog_t *prog)
2085 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
2086 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2088 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2089 MSG_WriteByte(&sv.datagram, TE_SPARK);
2091 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2092 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2093 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2095 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2096 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2097 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2099 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2100 SV_FlushBroadcastMessages();
2103 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2105 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2106 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2107 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2109 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2110 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2111 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2112 SV_FlushBroadcastMessages();
2115 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2117 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2118 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2119 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2121 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2122 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2123 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2124 SV_FlushBroadcastMessages();
2127 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2129 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2130 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2131 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2133 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2134 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2135 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2136 SV_FlushBroadcastMessages();
2139 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2141 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2142 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2143 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2145 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2146 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2147 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2148 SV_FlushBroadcastMessages();
2151 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2153 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2154 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2155 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2157 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2158 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2159 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2160 SV_FlushBroadcastMessages();
2163 static void VM_SV_te_customflash(prvm_prog_t *prog)
2165 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2166 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2168 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2169 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2171 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2172 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2173 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2175 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2177 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2179 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2180 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2181 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2182 SV_FlushBroadcastMessages();
2185 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2187 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2188 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2189 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2191 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2192 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2193 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2194 SV_FlushBroadcastMessages();
2197 static void VM_SV_te_spike(prvm_prog_t *prog)
2199 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2200 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2201 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2203 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2204 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2205 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2206 SV_FlushBroadcastMessages();
2209 static void VM_SV_te_superspike(prvm_prog_t *prog)
2211 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2212 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2213 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2215 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2216 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2217 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2218 SV_FlushBroadcastMessages();
2221 static void VM_SV_te_explosion(prvm_prog_t *prog)
2223 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2224 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2225 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2227 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2230 SV_FlushBroadcastMessages();
2233 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2235 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2236 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2237 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2239 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2240 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2241 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2242 SV_FlushBroadcastMessages();
2245 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2247 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2248 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2249 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2251 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2252 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2253 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2254 SV_FlushBroadcastMessages();
2257 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2259 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2260 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2261 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2263 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2264 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2265 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2266 SV_FlushBroadcastMessages();
2269 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2271 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2272 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2273 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2275 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2276 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2277 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2278 SV_FlushBroadcastMessages();
2281 static void VM_SV_te_teleport(prvm_prog_t *prog)
2283 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2284 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2285 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2287 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2288 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2289 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2290 SV_FlushBroadcastMessages();
2293 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2295 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2296 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2297 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2299 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2300 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2301 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2303 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2304 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2305 SV_FlushBroadcastMessages();
2308 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2310 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2311 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2312 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2314 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2316 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2317 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2318 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2320 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2321 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2322 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2323 SV_FlushBroadcastMessages();
2326 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2328 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2329 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2330 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2332 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2334 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2335 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2336 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2338 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2339 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2340 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2341 SV_FlushBroadcastMessages();
2344 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2346 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2347 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2348 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2350 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2352 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2353 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2354 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2356 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2357 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2358 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2359 SV_FlushBroadcastMessages();
2362 static void VM_SV_te_beam(prvm_prog_t *prog)
2364 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2365 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2366 MSG_WriteByte(&sv.datagram, TE_BEAM);
2368 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2370 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2371 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2372 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2374 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2375 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2376 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2377 SV_FlushBroadcastMessages();
2380 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2382 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2383 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2384 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2385 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2386 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2387 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2388 SV_FlushBroadcastMessages();
2391 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2393 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2394 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2395 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2397 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2398 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2399 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2401 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2402 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2403 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2405 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2406 SV_FlushBroadcastMessages();
2409 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2410 //this function originally written by KrimZon, made shorter by LadyHavoc
2411 static void VM_SV_clientcommand(prvm_prog_t *prog)
2413 client_t *temp_client;
2415 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2417 //find client for this entity
2418 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2419 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2421 Con_Print("PF_clientcommand: entity is not a client\n");
2425 temp_client = host_client;
2426 host_client = svs.clients + i;
2427 Cmd_ExecuteString(&cmd_serverfromclient, PRVM_G_STRING(OFS_PARM1), src_client, true);
2428 host_client = temp_client;
2431 //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)
2432 static void VM_SV_setattachment(prvm_prog_t *prog)
2434 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2435 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2436 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2439 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2441 if (e == prog->edicts)
2443 VM_Warning(prog, "setattachment: can not modify world entity\n");
2446 if (e->priv.server->free)
2448 VM_Warning(prog, "setattachment: can not modify free entity\n");
2452 if (tagentity == NULL)
2453 tagentity = prog->edicts;
2457 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2459 model = SV_GetModelFromEdict(tagentity);
2462 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2464 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);
2467 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));
2470 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2471 PRVM_serveredictfloat(e, tag_index) = tagindex;
2474 /////////////////////////////////////////
2475 // DP_MD3_TAGINFO extension coded by VorteX
2477 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2481 i = (int)PRVM_serveredictfloat(e, modelindex);
2482 if (i < 1 || i >= MAX_MODELS)
2485 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2488 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2495 Matrix4x4_CreateIdentity(tag_localmatrix);
2497 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2499 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2510 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2513 float pitchsign = 1;
2515 scale = PRVM_serveredictfloat(ent, scale);
2520 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);
2523 pitchsign = SV_GetPitchSign(prog, ent);
2524 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);
2528 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2531 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2533 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2534 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2535 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2536 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2538 *out = identitymatrix;
2542 // Warnings/errors code:
2543 // 0 - normal (everything all-right)
2546 // 3 - null or non-precached model
2547 // 4 - no tags with requested index
2548 // 5 - runaway loop at attachment chain
2549 extern cvar_t cl_bob;
2550 extern cvar_t cl_bobcycle;
2551 extern cvar_t cl_bobup;
2552 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2555 int modelindex, attachloop;
2556 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2559 *out = identitymatrix; // warnings and errors return identical matrix
2561 if (ent == prog->edicts)
2563 if (ent->priv.server->free)
2566 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2567 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2570 model = SV_GetModelByIndex(modelindex);
2572 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2573 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2574 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2576 tagmatrix = identitymatrix;
2577 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2581 if (attachloop >= 256) // prevent runaway looping
2583 // apply transformation by child's tagindex on parent entity and then
2584 // by parent entity itself
2585 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2586 if (ret && attachloop == 0)
2588 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2589 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2590 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2591 // next iteration we process the parent entity
2592 if (PRVM_serveredictedict(ent, tag_entity))
2594 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2595 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2602 // RENDER_VIEWMODEL magic
2603 if (PRVM_serveredictedict(ent, viewmodelforclient))
2605 Matrix4x4_Copy(&tagmatrix, out);
2606 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2608 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2609 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2612 // Cl_bob, ported from rendering code
2613 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2616 // LadyHavoc: this code is *weird*, but not replacable (I think it
2617 // should be done in QC on the server, but oh well, quake is quake)
2618 // LadyHavoc: figured out bobup: the time at which the sin is at 180
2619 // degrees (which allows lengthening or squishing the peak or valley)
2620 cycle = sv.time/cl_bobcycle.value;
2621 cycle -= (int)cycle;
2622 if (cycle < cl_bobup.value)
2623 cycle = sin(M_PI * cycle / cl_bobup.value);
2625 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2626 // bob is proportional to velocity in the xy plane
2627 // (don't count Z, or jumping messes it up)
2628 bob = sqrt(PRVM_serveredictvector(ent, velocity)[0]*PRVM_serveredictvector(ent, velocity)[0] + PRVM_serveredictvector(ent, velocity)[1]*PRVM_serveredictvector(ent, velocity)[1])*cl_bob.value;
2629 bob = bob*0.3 + bob*0.7*cycle;
2630 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2637 //float(entity ent, string tagname) gettagindex;
2639 static void VM_SV_gettagindex(prvm_prog_t *prog)
2642 const char *tag_name;
2645 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2647 ent = PRVM_G_EDICT(OFS_PARM0);
2648 tag_name = PRVM_G_STRING(OFS_PARM1);
2650 if (ent == prog->edicts)
2652 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2655 if (ent->priv.server->free)
2657 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2662 if (!SV_GetModelFromEdict(ent))
2663 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2666 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2668 if(developer_extra.integer)
2669 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2671 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2674 //vector(entity ent, float tagindex) gettaginfo;
2675 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2679 matrix4x4_t tag_matrix;
2680 matrix4x4_t tag_localmatrix;
2682 const char *tagname;
2684 vec3_t forward, left, up, origin;
2685 const dp_model_t *model;
2687 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2689 e = PRVM_G_EDICT(OFS_PARM0);
2690 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2692 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2693 Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
2694 VectorCopy(forward, PRVM_serverglobalvector(v_forward));
2695 VectorNegate(left, PRVM_serverglobalvector(v_right));
2696 VectorCopy(up, PRVM_serverglobalvector(v_up));
2697 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2698 model = SV_GetModelFromEdict(e);
2699 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2700 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2701 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2702 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2703 Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
2705 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2706 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2707 VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
2708 VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
2709 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2710 VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset));
2715 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2718 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2721 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2724 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2727 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2732 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2733 static void VM_SV_dropclient(prvm_prog_t *prog)
2736 client_t *oldhostclient;
2737 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2738 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2739 if (clientnum < 0 || clientnum >= svs.maxclients)
2741 VM_Warning(prog, "dropclient: not a client\n");
2744 if (!svs.clients[clientnum].active)
2746 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2749 oldhostclient = host_client;
2750 host_client = svs.clients + clientnum;
2751 SV_DropClient(false);
2752 host_client = oldhostclient;
2755 //entity() spawnclient (DP_SV_BOTCLIENT)
2756 static void VM_SV_spawnclient(prvm_prog_t *prog)
2760 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2761 prog->xfunction->builtinsprofile += 2;
2763 for (i = 0;i < svs.maxclients;i++)
2765 if (!svs.clients[i].active)
2767 prog->xfunction->builtinsprofile += 100;
2768 SV_ConnectClient (i, NULL);
2769 // this has to be set or else ClientDisconnect won't be called
2770 // we assume the qc will call ClientConnect...
2771 svs.clients[i].clientconnectcalled = true;
2772 ed = PRVM_EDICT_NUM(i + 1);
2776 VM_RETURN_EDICT(ed);
2779 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2780 static void VM_SV_clienttype(prvm_prog_t *prog)
2783 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2784 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2785 if (clientnum < 0 || clientnum >= svs.maxclients)
2786 PRVM_G_FLOAT(OFS_RETURN) = 3;
2787 else if (!svs.clients[clientnum].active)
2788 PRVM_G_FLOAT(OFS_RETURN) = 0;
2789 else if (svs.clients[clientnum].netconnection)
2790 PRVM_G_FLOAT(OFS_RETURN) = 1;
2792 PRVM_G_FLOAT(OFS_RETURN) = 2;
2799 string(string key) serverkey
2802 static void VM_SV_serverkey(prvm_prog_t *prog)
2804 char string[VM_STRINGTEMP_LENGTH];
2805 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2806 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2807 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2810 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2811 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2816 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2818 e = PRVM_G_EDICT(OFS_PARM0);
2819 if (e == prog->edicts)
2821 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2824 if (e->priv.server->free)
2826 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2829 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2830 if (i <= 0 || i >= MAX_MODELS)
2832 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2835 if (!sv.model_precache[i][0])
2837 VM_Warning(prog, "setmodelindex: model not precached\n");
2841 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2842 PRVM_serveredictfloat(e, modelindex) = i;
2844 mod = SV_GetModelByIndex(i);
2848 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2849 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2851 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2854 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2857 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2858 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2861 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2863 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2865 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2866 if (i <= 0 || i >= MAX_MODELS)
2868 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2871 if (!sv.model_precache[i][0])
2873 VM_Warning(prog, "modelnameforindex: model not precached\n");
2877 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2880 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2881 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2884 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2885 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2888 PRVM_G_FLOAT(OFS_RETURN) = i;
2891 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2892 static void VM_SV_trailparticles(prvm_prog_t *prog)
2895 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2897 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2900 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2901 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2902 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2903 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start);
2904 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end);
2905 MSG_WriteVector(&sv.datagram, start, sv.protocol);
2906 MSG_WriteVector(&sv.datagram, end, sv.protocol);
2907 SV_FlushBroadcastMessages();
2910 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2911 static void VM_SV_pointparticles(prvm_prog_t *prog)
2913 int effectnum, count;
2915 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2917 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2920 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2921 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2922 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2923 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2924 if (count == 1 && !VectorLength2(vel))
2927 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2928 MSG_WriteShort(&sv.datagram, effectnum);
2929 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2933 // 1+2+12+12+2=29 bytes
2934 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2935 MSG_WriteShort(&sv.datagram, effectnum);
2936 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2937 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2938 MSG_WriteShort(&sv.datagram, count);
2941 SV_FlushBroadcastMessages();
2944 //PF_setpause, // void(float pause) setpause = #531;
2945 static void VM_SV_setpause(prvm_prog_t *prog) {
2947 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2948 if (pauseValue != 0) { //pause the game
2950 sv.pausedstart = host.realtime;
2951 } else { //disable pause, in case it was enabled
2952 if (sv.paused != 0) {
2957 // send notification to all clients
2958 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2959 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2962 // #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.
2963 static void VM_SV_skel_create(prvm_prog_t *prog)
2965 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2966 dp_model_t *model = SV_GetModelByIndex(modelindex);
2967 skeleton_t *skeleton;
2969 PRVM_G_FLOAT(OFS_RETURN) = 0;
2970 if (!model || !model->num_bones)
2972 for (i = 0;i < MAX_EDICTS;i++)
2973 if (!prog->skeletons[i])
2975 if (i == MAX_EDICTS)
2977 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(prog->progs_mempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2978 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2979 skeleton->model = model;
2980 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2981 // initialize to identity matrices
2982 for (i = 0;i < skeleton->model->num_bones;i++)
2983 skeleton->relativetransforms[i] = identitymatrix;
2986 // #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
2987 static void VM_SV_skel_build(prvm_prog_t *prog)
2989 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2990 skeleton_t *skeleton;
2991 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2992 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2993 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2994 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2995 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2996 dp_model_t *model = SV_GetModelByIndex(modelindex);
3000 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
3001 frameblend_t frameblend[MAX_FRAMEBLENDS];
3002 matrix4x4_t bonematrix;
3004 PRVM_G_FLOAT(OFS_RETURN) = 0;
3005 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3007 firstbone = max(0, firstbone);
3008 lastbone = min(lastbone, model->num_bones - 1);
3009 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3010 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
3011 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time);
3012 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
3014 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3016 memset(&bonematrix, 0, sizeof(bonematrix));
3017 for (blendindex = 0;blendindex < numblends;blendindex++)
3019 Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
3020 Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp);
3022 Matrix4x4_Normalize3(&bonematrix, &bonematrix);
3023 Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac);
3025 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
3028 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3029 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
3031 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3032 skeleton_t *skeleton;
3033 PRVM_G_FLOAT(OFS_RETURN) = 0;
3034 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3036 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
3039 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
3040 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
3042 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3043 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3044 skeleton_t *skeleton;
3045 PRVM_G_INT(OFS_RETURN) = 0;
3046 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3048 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3050 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
3053 // #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)
3054 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
3056 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3057 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3058 skeleton_t *skeleton;
3059 PRVM_G_FLOAT(OFS_RETURN) = 0;
3060 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3062 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3064 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
3067 // #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
3068 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
3070 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3071 const char *tagname = PRVM_G_STRING(OFS_PARM1);
3072 skeleton_t *skeleton;
3073 PRVM_G_FLOAT(OFS_RETURN) = 0;
3074 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3076 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
3079 // #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)
3080 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
3082 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3083 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3084 skeleton_t *skeleton;
3086 vec3_t forward, left, up, origin;
3087 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3088 VectorClear(PRVM_clientglobalvector(v_forward));
3089 VectorClear(PRVM_clientglobalvector(v_right));
3090 VectorClear(PRVM_clientglobalvector(v_up));
3091 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3093 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3095 matrix = skeleton->relativetransforms[bonenum];
3096 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3097 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3098 VectorNegate(left, PRVM_clientglobalvector(v_right));
3099 VectorCopy(up, PRVM_clientglobalvector(v_up));
3100 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3103 // #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)
3104 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
3106 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3107 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3108 skeleton_t *skeleton;
3111 vec3_t forward, left, up, origin;
3112 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3113 VectorClear(PRVM_clientglobalvector(v_forward));
3114 VectorClear(PRVM_clientglobalvector(v_right));
3115 VectorClear(PRVM_clientglobalvector(v_up));
3116 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3118 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3120 matrix = skeleton->relativetransforms[bonenum];
3121 // convert to absolute
3122 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3125 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3127 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3128 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3129 VectorNegate(left, PRVM_clientglobalvector(v_right));
3130 VectorCopy(up, PRVM_clientglobalvector(v_up));
3131 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3134 // #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)
3135 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3137 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3138 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3139 vec3_t forward, left, up, origin;
3140 skeleton_t *skeleton;
3142 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3144 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3146 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3147 VectorNegate(PRVM_clientglobalvector(v_right), left);
3148 VectorCopy(PRVM_clientglobalvector(v_up), up);
3149 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3150 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3151 skeleton->relativetransforms[bonenum] = matrix;
3154 // #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)
3155 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3157 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3158 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3159 vec3_t forward, left, up, origin;
3160 skeleton_t *skeleton;
3163 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3165 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3167 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3168 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3169 VectorNegate(PRVM_clientglobalvector(v_right), left);
3170 VectorCopy(PRVM_clientglobalvector(v_up), up);
3171 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3172 temp = skeleton->relativetransforms[bonenum];
3173 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3176 // #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)
3177 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3179 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3180 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3181 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3183 vec3_t forward, left, up, origin;
3184 skeleton_t *skeleton;
3187 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3189 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3190 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3191 VectorNegate(PRVM_clientglobalvector(v_right), left);
3192 VectorCopy(PRVM_clientglobalvector(v_up), up);
3193 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3194 firstbone = max(0, firstbone);
3195 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3196 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3198 temp = skeleton->relativetransforms[bonenum];
3199 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3203 // #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
3204 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3206 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3207 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3208 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3209 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3211 skeleton_t *skeletondst;
3212 skeleton_t *skeletonsrc;
3213 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3215 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3217 firstbone = max(0, firstbone);
3218 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3219 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3220 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3221 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3224 // #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)
3225 static void VM_SV_skel_delete(prvm_prog_t *prog)
3227 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3228 skeleton_t *skeleton;
3229 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3232 prog->skeletons[skeletonindex] = NULL;
3235 // #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
3236 static void VM_SV_frameforname(prvm_prog_t *prog)
3238 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3239 dp_model_t *model = SV_GetModelByIndex(modelindex);
3240 const char *name = PRVM_G_STRING(OFS_PARM1);
3242 PRVM_G_FLOAT(OFS_RETURN) = -1;
3243 if (!model || !model->animscenes)
3245 for (i = 0;i < model->numframes;i++)
3247 if (!strcasecmp(model->animscenes[i].name, name))
3249 PRVM_G_FLOAT(OFS_RETURN) = i;
3255 // #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.
3256 static void VM_SV_frameduration(prvm_prog_t *prog)
3258 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3259 dp_model_t *model = SV_GetModelByIndex(modelindex);
3260 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3261 PRVM_G_FLOAT(OFS_RETURN) = 0;
3262 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3264 if (model->animscenes[framenum].framerate)
3265 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3268 // #700 float() nodegraph_graphset_clear (EXT_NODEGRAPH)
3269 static void VM_nodegraph_graphset_clear(prvm_prog_t *prog)
3271 VM_SAFEPARMCOUNT(0, VM_nodegraph_graphset_clear);
3273 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_graphset_clear();
3276 // #701 float() nodegraph_graphset_load (EXT_NODEGRAPH)
3277 static void VM_nodegraph_graphset_load(prvm_prog_t *prog)
3279 VM_SAFEPARMCOUNT(0, VM_nodegraph_graphset_load);
3281 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_graphset_load();
3284 // #702 float() nodegraph_graphset_save (EXT_NODEGRAPH)
3285 static void VM_nodegraph_graphset_save(prvm_prog_t *prog)
3287 VM_SAFEPARMCOUNT(0, VM_nodegraph_graphset_save);
3289 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_graphset_save();
3292 // #703 float(float graphid) nodegraph_graph_clear (EXT_NODEGRAPH)
3293 static void VM_nodegraph_graph_clear(prvm_prog_t *prog)
3297 VM_SAFEPARMCOUNT(1, VM_nodegraph_graph_clear);
3299 graphid = (short)PRVM_G_FLOAT(OFS_PARM0);
3301 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_graph_clear(graphid);
3304 // #704 float(float graphid) nodegraph_graph_nodes_count (EXT_NODEGRAPH)
3305 static void VM_nodegraph_graph_nodes_count(prvm_prog_t *prog)
3309 VM_SAFEPARMCOUNT(1, VM_nodegraph_graph_nodes_count);
3311 graphid = (short)PRVM_G_FLOAT(OFS_PARM0);
3313 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_graph_nodes_count(graphid);
3316 // #705 float(float graphid, vector node) nodegraph_graph_add_node (EXT_NODEGRAPH)
3317 static void VM_nodegraph_graph_add_node(prvm_prog_t *prog)
3322 VM_SAFEPARMCOUNT(2, VM_nodegraph_graph_add_node);
3324 graphid = (short)PRVM_G_FLOAT(OFS_PARM0);
3325 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), node);
3327 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_graph_add_node(graphid, node);
3330 // #706 float(float graphid, float nodeid) nodegraph_graph_remove_node (EXT_NODEGRAPH)
3331 static void VM_nodegraph_graph_remove_node(prvm_prog_t *prog)
3336 VM_SAFEPARMCOUNT(2, VM_nodegraph_graph_remove_node);
3338 graphid = (short)PRVM_G_FLOAT(OFS_PARM0);
3339 nodeid = (short)PRVM_G_FLOAT(OFS_PARM1);
3341 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_graph_remove_node(graphid, nodeid);
3344 // #707 float(float graphid, float nodeid) nodegraph_graph_is_node_valid (EXT_NODEGRAPH)
3345 static void VM_nodegraph_graph_is_node_valid(prvm_prog_t *prog)
3350 VM_SAFEPARMCOUNT(2, VM_nodegraph_graph_is_node_valid);
3352 graphid = (short)PRVM_G_FLOAT(OFS_PARM0);
3353 nodeid = (short)PRVM_G_FLOAT(OFS_PARM1);
3355 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_graph_is_node_valid(graphid, nodeid);
3358 // #708 vector(float graphid, float nodeid) nodegraph_graph_get_node (EXT_NODEGRAPH)
3359 static void VM_nodegraph_graph_get_node(prvm_prog_t *prog)
3365 VM_SAFEPARMCOUNT(2, VM_nodegraph_graph_get_node);
3367 graphid = (short)PRVM_G_FLOAT(OFS_PARM0);
3368 nodeid = (short)PRVM_G_FLOAT(OFS_PARM1);
3370 nodegraph_graph_get_node(graphid, nodeid, outnode);
3372 VectorCopy(outnode, PRVM_G_VECTOR(OFS_RETURN));
3375 // #709 float(float graphid, float nodeidfrom, float nodeidto) nodegraph_graph_add_link (EXT_NODEGRAPH)
3376 static void VM_nodegraph_graph_add_link(prvm_prog_t *prog)
3382 VM_SAFEPARMCOUNT(3, VM_nodegraph_graph_add_link);
3384 graphid = (short)PRVM_G_FLOAT(OFS_PARM0);
3385 nodeidfrom = (short)PRVM_G_FLOAT(OFS_PARM1);
3386 nodeidto = (short)PRVM_G_FLOAT(OFS_PARM2);
3388 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_graph_add_link(graphid, nodeidfrom, nodeidto);
3391 // #710 float(float graphid, float nodeidfrom, float nodeidto) nodegraph_graph_remove_link (EXT_NODEGRAPH)
3392 static void VM_nodegraph_graph_remove_link(prvm_prog_t *prog)
3398 VM_SAFEPARMCOUNT(3, VM_nodegraph_graph_remove_link);
3400 graphid = (short)PRVM_G_FLOAT(OFS_PARM0);
3401 nodeidfrom = (short)PRVM_G_FLOAT(OFS_PARM1);
3402 nodeidto = (short)PRVM_G_FLOAT(OFS_PARM2);
3404 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_graph_remove_link(graphid, nodeidfrom, nodeidto);
3406 // #711 float(float graphid, float nodeidfrom, float nodeidto) nodegraph_graph_does_link_exist (EXT_NODEGRAPH)
3407 static void VM_nodegraph_graph_does_link_exist(prvm_prog_t *prog)
3413 VM_SAFEPARMCOUNT(3, VM_nodegraph_graph_does_link_exist);
3415 graphid = (short)PRVM_G_FLOAT(OFS_PARM0);
3416 nodeidfrom = (short)PRVM_G_FLOAT(OFS_PARM1);
3417 nodeidto = (short)PRVM_G_FLOAT(OFS_PARM2);
3419 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_graph_does_link_exist(graphid, nodeidfrom, nodeidto);
3422 // #712 float(float graphid, vector position) nodegraph_graph_find_nearest_nodeid (EXT_NODEGRAPH)
3423 static void VM_nodegraph_graph_find_nearest_nodeid(prvm_prog_t *prog)
3428 VM_SAFEPARMCOUNT(2, VM_nodegraph_graph_find_nearest_nodeid);
3430 graphid = (short)PRVM_G_FLOAT(OFS_PARM0);
3431 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), position);
3433 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_graph_find_nearest_nodeid(graphid, position);
3436 // #713 float(float graphid, float nodeidfrom, float nodeidto) nodegraph_graph_query_path (EXT_NODEGRAPH)
3437 static void VM_nodegraph_graph_query_path(prvm_prog_t *prog)
3443 VM_SAFEPARMCOUNT(3, VM_nodegraph_graph_query_path);
3445 graphid = (short)PRVM_G_FLOAT(OFS_PARM0);
3446 nodeidfrom = (short)PRVM_G_FLOAT(OFS_PARM1);
3447 nodeidto = (short)PRVM_G_FLOAT(OFS_PARM2);
3449 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_graph_query_path(graphid, nodeidfrom, nodeidto);
3452 // #714 float(float graphid, float nodeid) nodegraph_graph_query_nodes_linked (EXT_NODEGRAPH)
3453 static void VM_nodegraph_graph_query_nodes_linked(prvm_prog_t *prog)
3458 VM_SAFEPARMCOUNT(2, VM_nodegraph_graph_query_nodes_linked);
3460 graphid = (short)PRVM_G_FLOAT(OFS_PARM0);
3461 nodeid = (short)PRVM_G_FLOAT(OFS_PARM1);
3463 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_graph_query_nodes_linked(graphid, nodeid);
3466 // #715 float(float graphid, vector position, float radius) nodegraph_graph_query_nodes_in_radius (EXT_NODEGRAPH)
3467 static void VM_nodegraph_graph_query_nodes_in_radius(prvm_prog_t *prog)
3473 VM_SAFEPARMCOUNT(3, VM_nodegraph_graph_query_nodes_in_radius);
3475 graphid = (short)PRVM_G_FLOAT(OFS_PARM0);
3476 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), position);
3477 radius = PRVM_G_FLOAT(OFS_PARM2);
3479 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_graph_query_nodes_in_radius(graphid, position, radius);
3482 // #716 float(float queryid) nodegraph_query_release (EXT_NODEGRAPH)
3483 static void VM_nodegraph_query_release(prvm_prog_t *prog)
3487 VM_SAFEPARMCOUNT(1, VM_nodegraph_query_release);
3489 queryid = (short)PRVM_G_FLOAT(OFS_PARM0);
3491 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_query_release(queryid);
3494 // #717 float(float queryid) nodegraph_query_entries_count (EXT_NODEGRAPH)
3495 static void VM_nodegraph_query_entries_count(prvm_prog_t *prog)
3499 VM_SAFEPARMCOUNT(1, VM_nodegraph_query_entries_count);
3501 queryid = (short)PRVM_G_FLOAT(OFS_PARM0);
3503 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_query_entries_count(queryid);
3506 // #718 float(float queryid) nodegraph_query_is_valid (EXT_NODEGRAPH)
3507 static void VM_nodegraph_query_is_valid(prvm_prog_t *prog)
3511 VM_SAFEPARMCOUNT(1, VM_nodegraph_query_is_valid);
3513 queryid = (short)PRVM_G_FLOAT(OFS_PARM0);
3515 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_query_is_valid(queryid);
3518 // #719 float(float queryid) nodegraph_query_get_graphid (EXT_NODEGRAPH)
3519 static void VM_nodegraph_query_get_graphid(prvm_prog_t *prog)
3523 VM_SAFEPARMCOUNT(1, VM_nodegraph_query_get_graphid);
3525 queryid = (short)PRVM_G_FLOAT(OFS_PARM0);
3527 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_query_get_graphid(queryid);
3530 // #720 float(float queryid, float entryid) nodegraph_query_get_nodeid (EXT_NODEGRAPH)
3531 static void VM_nodegraph_query_get_nodeid(prvm_prog_t *prog)
3536 VM_SAFEPARMCOUNT(2, VM_nodegraph_query_get_nodeid);
3538 queryid = (short)PRVM_G_FLOAT(OFS_PARM0);
3539 entryid = (short)PRVM_G_FLOAT(OFS_PARM1);
3541 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_query_get_nodeid(queryid, entryid);
3544 // #721 float(vector nodefrom, vector nodeto, vector mins, vector maxs, float type) nodegraph_moveprobe_fly (EXT_NODEGRAPH)
3545 static void VM_nodegraph_moveprobe_fly(prvm_prog_t *prog)
3553 VM_SAFEPARMCOUNT(5, VM_nodegraph_moveprobe_fly);
3555 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), nodefrom);
3556 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), nodeto);
3557 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), mins);
3558 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), maxs);
3560 type = (short)PRVM_G_FLOAT(OFS_PARM4);
3562 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_moveprobe_fly(nodefrom, nodeto, mins, maxs, type);
3565 // #722 (vector nodefrom, vector nodeto, vector mins, vector maxs, float stepheight, float dropheight) nodegraph_moveprobe_walk (EXT_NODEGRAPH)
3566 static void VM_nodegraph_moveprobe_walk(prvm_prog_t *prog)
3575 VM_SAFEPARMCOUNT(6, VM_nodegraph_moveprobe_walk);
3577 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), nodefrom);
3578 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), nodeto);
3579 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), mins);
3580 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), maxs);
3582 stepheight = PRVM_G_FLOAT(OFS_PARM4);
3583 dropheight = PRVM_G_FLOAT(OFS_PARM5);
3585 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_moveprobe_walk(nodefrom, nodeto, mins, maxs, stepheight, dropheight);
3588 // #723 float(float graphid, vector position, float radius, vector mins, vector maxs, float type) nodegraph_graph_query_nodes_in_radius_fly_reachable (EXT_NODEGRAPH)
3589 static void VM_nodegraph_graph_query_nodes_in_radius_fly_reachable(prvm_prog_t *prog)
3598 VM_SAFEPARMCOUNT(6, VM_nodegraph_graph_query_nodes_in_radius_fly_reachable);
3600 graphid = (short)PRVM_G_FLOAT(OFS_PARM0);
3602 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), position);
3604 radius = PRVM_G_FLOAT(OFS_PARM2);
3606 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), mins);
3607 VectorCopy(PRVM_G_VECTOR(OFS_PARM4), maxs);
3609 type = (short)PRVM_G_FLOAT(OFS_PARM5);
3611 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_graph_query_nodes_in_radius_fly_reachable(graphid, position, radius, mins, maxs, type);
3614 // #724 float(float graphid, vector position, float radius, vector mins, vector maxs, float stepheight, float dropheight) nodegraph_graph_query_nodes_in_radius_walk_reachable (EXT_NODEGRAPH)
3615 static void VM_nodegraph_graph_query_nodes_in_radius_walk_reachable(prvm_prog_t *prog)
3625 VM_SAFEPARMCOUNT(7, VM_nodegraph_graph_query_nodes_in_radius_walk_reachable);
3627 graphid = (short)PRVM_G_FLOAT(OFS_PARM0);
3629 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), position);
3631 radius = PRVM_G_FLOAT(OFS_PARM2);
3633 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), mins);
3634 VectorCopy(PRVM_G_VECTOR(OFS_PARM4), maxs);
3636 stepheight = PRVM_G_FLOAT(OFS_PARM5);
3637 dropheight = PRVM_G_FLOAT(OFS_PARM6);
3639 PRVM_G_FLOAT(OFS_RETURN) = (float)nodegraph_graph_query_nodes_in_radius_walk_reachable(graphid, position, radius, mins, maxs, stepheight, dropheight);
3641 prvm_builtin_t vm_sv_builtins[] = {
3642 NULL, // #0 NULL function (not callable) (QUAKE)
3643 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3644 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3645 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3646 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3647 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3648 VM_break, // #6 void() break (QUAKE)
3649 VM_random, // #7 float() random (QUAKE)
3650 VM_SV_sound, // #8 void(entity e, float chan, string samp, float volume[, float atten[, float pitchchange[, float flags]]]) sound (QUAKE)
3651 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3652 VM_error, // #10 void(string e) error (QUAKE)
3653 VM_objerror, // #11 void(string e) objerror (QUAKE)
3654 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3655 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3656 VM_spawn, // #14 entity() spawn (QUAKE)
3657 VM_remove, // #15 void(entity e) remove (QUAKE)
3658 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3659 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3660 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3661 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3662 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3663 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3664 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3665 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3666 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3667 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3668 VM_ftos, // #26 string(float f) ftos (QUAKE)
3669 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3670 VM_coredump, // #28 void() coredump (QUAKE)
3671 VM_traceon, // #29 void() traceon (QUAKE)
3672 VM_traceoff, // #30 void() traceoff (QUAKE)
3673 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3674 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3675 NULL, // #33 (QUAKE)
3676 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3677 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3678 VM_rint, // #36 float(float v) rint (QUAKE)
3679 VM_floor, // #37 float(float v) floor (QUAKE)
3680 VM_ceil, // #38 float(float v) ceil (QUAKE)
3681 NULL, // #39 (QUAKE)
3682 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3683 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3684 NULL, // #42 (QUAKE)
3685 VM_fabs, // #43 float(float f) fabs (QUAKE)
3686 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3687 VM_cvar, // #45 float(string s) cvar (QUAKE)
3688 VM_localcmd_server, // #46 void(string s) localcmd (QUAKE)
3689 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3690 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3691 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3692 NULL, // #50 (QUAKE)
3693 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3694 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3695 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3696 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3697 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3698 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3699 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3700 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3701 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3702 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3703 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3704 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3705 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3706 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3707 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3708 NULL, // #66 (QUAKE)
3709 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3710 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3711 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3712 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3713 NULL, // #71 (QUAKE)
3714 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3715 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3716 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3717 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3718 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3719 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3720 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3721 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3722 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3723 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3724 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3725 NULL, // #83 (QUAKE)
3726 NULL, // #84 (QUAKE)
3727 NULL, // #85 (QUAKE)
3728 NULL, // #86 (QUAKE)
3729 NULL, // #87 (QUAKE)
3730 NULL, // #88 (QUAKE)
3731 NULL, // #89 (QUAKE)
3732 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3733 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3734 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3735 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3736 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3737 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3738 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3739 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3740 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3741 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3742 // FrikaC and Telejano range #100-#199
3753 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3754 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3755 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3756 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3757 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3758 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3759 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3760 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3761 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3762 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3843 // FTEQW range #200-#299
3862 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3865 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3866 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3867 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3868 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3869 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3870 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3871 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3872 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3873 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3874 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3876 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3884 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3907 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.
3908 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
3909 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3910 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3911 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)
3912 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
3913 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)
3914 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)
3915 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)
3916 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)
3917 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)
3918 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
3919 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)
3920 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
3921 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.
3944 // CSQC range #300-#399
3945 NULL, // #300 void() clearscene (EXT_CSQC)
3946 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3947 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3948 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3949 NULL, // #304 void() renderscene (EXT_CSQC)
3950 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3951 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3952 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3953 NULL, // #308 void() R_EndPolygon
3955 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3956 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3960 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3961 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3962 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3963 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3964 NULL, // #319 void(string name) freepic (EXT_CSQC)
3965 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3966 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3967 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3968 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3969 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3970 NULL, // #325 void(void) drawresetcliparea
3975 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3976 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3977 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3978 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3979 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3980 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3981 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3982 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3983 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3984 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3985 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3986 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3987 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3988 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3989 NULL, // #344 vector() getmousepos (EXT_CSQC)
3990 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3991 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3992 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3993 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3994 NULL, // #349 float() isdemo (EXT_CSQC)
3995 VM_isserver, // #350 float() isserver (EXT_CSQC)
3996 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3997 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3998 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3999 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
4005 NULL, // #360 float() readbyte (EXT_CSQC)
4006 NULL, // #361 float() readchar (EXT_CSQC)
4007 NULL, // #362 float() readshort (EXT_CSQC)
4008 NULL, // #363 float() readlong (EXT_CSQC)
4009 NULL, // #364 float() readcoord (EXT_CSQC)
4010 NULL, // #365 float() readangle (EXT_CSQC)
4011 NULL, // #366 string() readstring (EXT_CSQC)
4012 NULL, // #367 float() readfloat (EXT_CSQC)
4045 // LadyHavoc's range #400-#499
4046 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
4047 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
4048 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
4049 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
4050 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
4051 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
4052 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
4053 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
4054 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)
4055 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
4056 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
4057 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
4058 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
4059 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
4060 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
4061 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
4062 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
4063 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
4064 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
4065 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
4066 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
4067 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
4068 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
4069 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
4070 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
4071 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
4072 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
4073 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
4074 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
4075 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
4076 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
4077 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
4078 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
4079 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
4080 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
4081 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
4082 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
4083 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
4084 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
4085 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
4086 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
4087 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
4088 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
4089 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
4090 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
4091 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
4092 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
4093 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
4094 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
4095 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
4096 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
4097 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
4098 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
4099 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
4100 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
4101 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
4102 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
4103 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
4105 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
4106 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
4107 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
4108 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
4109 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
4110 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
4111 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
4112 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
4113 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
4114 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
4115 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
4117 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
4118 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
4119 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
4120 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
4121 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
4122 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
4123 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
4124 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
4125 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
4126 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
4127 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
4128 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
4129 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
4130 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
4131 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
4132 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
4140 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
4141 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
4142 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
4143 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
4144 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
4145 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
4146 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
4147 VM_SV_WritePicture, // #501
4149 VM_whichpack, // #503 string(string) whichpack = #503;
4156 VM_uri_escape, // #510 string(string in) uri_escape = #510;
4157 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
4158 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
4159 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)
4160 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
4161 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
4162 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
4163 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
4164 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
4165 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
4175 VM_loadfromdata, // #529
4176 VM_loadfromfile, // #530
4177 VM_SV_setpause, // #531 void(float pause) setpause = #531;
4179 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
4180 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
4181 VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP)
4182 VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP)
4183 VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP)
4184 VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP)
4186 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
4187 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
4188 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
4251 VM_callfunction, // #605
4252 VM_writetofile, // #606
4253 VM_isfunction, // #607
4259 VM_parseentitydata, // #613
4270 VM_SV_getextresponse, // #624 string getextresponse(void)
4273 VM_sprintf, // #627 string sprintf(string format, ...)
4274 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
4275 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
4285 VM_digest_hex, // #639
4288 VM_coverage, // #642
4296 // WRATH range (#650-#???)
4297 VM_fcopy, // #650 float(string fnfrom, string fnto) fcopy (EXT_WRATH)
4298 VM_frename, // #651 float (string fnold, string fnnew) frename (EXT_WRATH)
4299 VM_fremove, // #652 float (string fname) fremove (EXT_WRATH)
4300 VM_fexists, // #653 float (string fname) fexists (EXT_WRATH)
4301 VM_rmtree, // #654 float (string path) rmtree (EXT_WRATH)
4302 VM_SV_walkmovedist, // #655 float (float yaw, float dist[, float settrace]) walkmovedist (EXT_WRATH)
4347 VM_nodegraph_graphset_clear, // #700 float() nodegraph_graphset_clear (EXT_NODEGRAPH)
4348 VM_nodegraph_graphset_load, // #701 float() nodegraph_graphset_load (EXT_NODEGRAPH)
4349 VM_nodegraph_graphset_save, // #702 float() nodegraph_graphset_save (EXT_NODEGRAPH)
4350 VM_nodegraph_graph_clear, // #703 float(float graphid) nodegraph_graph_clear (EXT_NODEGRAPH)
4351 VM_nodegraph_graph_nodes_count, // #704 float(float graphid) nodegraph_graph_nodes_count (EXT_NODEGRAPH)
4352 VM_nodegraph_graph_add_node, // #705 float(float graphid, vector node) nodegraph_graph_add_node (EXT_NODEGRAPH)
4353 VM_nodegraph_graph_remove_node, // #706 float(float graphid, float nodeid) nodegraph_graph_remove_node (EXT_NODEGRAPH)
4354 VM_nodegraph_graph_is_node_valid, // #707 float(float graphid, float nodeid) nodegraph_graph_is_node_valid (EXT_NODEGRAPH)
4355 VM_nodegraph_graph_get_node, // #708 vector(float graphid, float nodeid) nodegraph_graph_get_node (EXT_NODEGRAPH)
4356 VM_nodegraph_graph_add_link, // #709 float(float graphid, float nodeidfrom, float nodeidto) nodegraph_graph_add_link (EXT_NODEGRAPH)
4357 VM_nodegraph_graph_remove_link, // #710 float(float graphid, float nodeidfrom, float nodeidto) nodegraph_graph_remove_link (EXT_NODEGRAPH)
4358 VM_nodegraph_graph_does_link_exist, // #711 float(float graphid, float nodeidfrom, float nodeidto) nodegraph_graph_does_link_exist (EXT_NODEGRAPH)
4359 VM_nodegraph_graph_find_nearest_nodeid, // #712 float(float graphid, vector position) nodegraph_graph_find_nearest_nodeid (EXT_NODEGRAPH)
4360 VM_nodegraph_graph_query_path, // #713 float(float graphid, float nodeidfrom, float nodeidto) nodegraph_graph_query_path (EXT_NODEGRAPH)
4361 VM_nodegraph_graph_query_nodes_linked, // #714 float(float graphid, float nodeid) nodegraph_graph_query_nodes_linked (EXT_NODEGRAPH)
4362 VM_nodegraph_graph_query_nodes_in_radius, // #715 float(float graphid, vector position, float radius) nodegraph_graph_query_nodes_in_radius (EXT_NODEGRAPH)
4363 VM_nodegraph_query_release, // #716 float(float queryid) nodegraph_query_release (EXT_NODEGRAPH)
4364 VM_nodegraph_query_entries_count, // #717 float(float queryid) nodegraph_query_entries_count (EXT_NODEGRAPH)
4365 VM_nodegraph_query_is_valid, // #718 float(float queryid) nodegraph_query_is_valid (EXT_NODEGRAPH)
4366 VM_nodegraph_query_get_graphid, // #719 float(float queryid) nodegraph_query_get_graphid (EXT_NODEGRAPH)
4367 VM_nodegraph_query_get_nodeid, // #720 float(float queryid, float entryid) nodegraph_query_get_nodeid (EXT_NODEGRAPH)
4368 VM_nodegraph_moveprobe_fly, // #721 float(vector nodefrom, vector nodeto, vector mins, vector maxs, float type) nodegraph_moveprobe_fly (EXT_NODEGRAPH)
4369 VM_nodegraph_moveprobe_walk, // #722 (vector nodefrom, vector nodeto, vector mins, vector maxs, float stepheight, float dropheight) nodegraph_moveprobe_walk (EXT_NODEGRAPH)
4370 VM_nodegraph_graph_query_nodes_in_radius_fly_reachable, // #723 float(float graphid, vector position, float radius, vector mins, vector maxs, float type) nodegraph_graph_query_nodes_in_radius_fly_reachable (EXT_NODEGRAPH)
4371 VM_nodegraph_graph_query_nodes_in_radius_walk_reachable, // #724 float(float graphid, vector position, float radius, vector mins, vector maxs, float stepheight, float dropheight) nodegraph_graph_query_nodes_in_radius_walk_reachable (EXT_NODEGRAPH)
4400 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
4402 void SVVM_init_cmd(prvm_prog_t *prog)
4407 void SVVM_reset_cmd(prvm_prog_t *prog)
4409 World_End(&sv.world);
4411 if(prog->loaded && PRVM_serverfunction(SV_Shutdown))
4413 func_t s = PRVM_serverfunction(SV_Shutdown);
4414 PRVM_serverglobalfloat(time) = sv.time;
4415 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
4416 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");