6 //============================================================================
11 const char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
25 "DP_CSQC_ENTITYWORLDOBJECT "
26 "DP_CSQC_ENTITYMODELLIGHT "
27 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
29 "DP_CSQC_MINFPS_QUALITY "
30 "DP_CSQC_MULTIFRAME_INTERPOLATION "
31 "DP_CSQC_BOXPARTICLES "
32 "DP_CSQC_SPAWNPARTICLE "
33 "DP_CSQC_QUERYRENDERENTITY "
34 "DP_CSQC_ROTATEMOVES "
36 "DP_CSQC_V_CALCREFDEF_WIP1 "
37 "DP_CSQC_V_CALCREFDEF_WIP2 "
41 "DP_EF_DYNAMICMODELLIGHT "
50 "DP_EF_RESTARTANIM_BIT "
55 "DP_ENT_CUSTOMCOLORMAP "
56 "DP_ENT_EXTERIORMODELTOCLIENT "
59 "DP_ENT_LOWPRECISION "
61 "DP_ENT_TRAILEFFECTNUM "
63 "DP_GFX_EXTERNALTEXTURES "
64 "DP_GFX_EXTERNALTEXTURES_PERMAP "
66 "DP_GFX_MODEL_INTERPOLATION "
67 "DP_GFX_QUAKE3MODELTAGS "
71 "DP_GFX_FONTS_FREETYPE "
73 "DP_FONT_VARIABLEWIDTH "
75 "DP_HALFLIFE_MAP_CVAR "
78 "DP_LIGHTSTYLE_STATICVALUE "
82 "DP_MOVETYPEBOUNCEMISSILE "
83 "DP_MOVETYPEFLYWORLDONLY "
86 "DP_QC_ASINACOSATANATAN2TAN "
92 "DP_QC_CVAR_DEFSTRING "
93 "DP_QC_CVAR_DESCRIPTION "
97 "DP_QC_DIGEST_SHA256 "
100 "DP_QC_ENTITYSTRING "
102 "DP_QC_EXTRESPONSEPACKET "
104 "DP_QC_FINDCHAINFLAGS "
105 "DP_QC_FINDCHAINFLOAT "
106 "DP_QC_FINDCHAIN_TOFIELD "
112 "DP_QC_GETSURFACETRIANGLE "
113 "DP_QC_GETSURFACEPOINTATTRIBUTE "
115 "DP_QC_GETTAGINFO_BONEPROPERTIES "
117 "DP_QC_GETTIME_CDTRACK "
121 "DP_QC_MULTIPLETEMPSTRINGS "
122 "DP_QC_NUM_FOR_EDICT "
124 "DP_QC_SINCOSSQRTPOW "
127 "DP_QC_STRINGBUFFERS "
128 "DP_QC_STRINGBUFFERS_CVARLIST "
129 "DP_QC_STRINGBUFFERS_EXT_WIP "
130 "DP_QC_STRINGCOLORFUNCTIONS "
131 "DP_QC_STRING_CASE_FUNCTIONS "
133 "DP_QC_TOKENIZEBYSEPARATOR "
134 "DP_QC_TOKENIZE_CONSOLE "
137 "DP_QC_TRACE_MOVETYPE_HITMODEL "
138 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
139 "DP_QC_UNLIMITEDTEMPSTRINGS "
143 "DP_QC_VECTOANGLES_WITH_ROLL "
144 "DP_QC_VECTORVECTORS "
151 "DP_SKELETONOBJECTS "
152 "DP_SND_DIRECTIONLESSATTNNONE "
154 "DP_SND_SOUND7_WIP1 "
155 "DP_SND_SOUND7_WIP2 "
159 "DP_SND_GETSOUNDTIME "
161 "DP_VIDEO_SUBTITLES "
165 "DP_SV_BOUNCEFACTOR "
166 "DP_SV_CLIENTCAMERA "
167 "DP_SV_CLIENTCOLORS "
170 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
171 "DP_SV_DISABLECLIENTPREDICTION "
172 "DP_SV_DISCARDABLEDEMO "
173 "DP_SV_DRAWONLYTOCLIENT "
176 "DP_SV_ENTITYCONTENTSTRANSITION "
177 "DP_SV_MODELFLAGS_AS_EFFECTS "
178 "DP_SV_MOVETYPESTEP_LANDEVENT "
180 "DP_SV_NODRAWTOCLIENT "
181 "DP_SV_ONENTITYNOSPAWNFUNCTION "
182 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
184 "DP_SV_PING_PACKETLOSS "
185 "DP_SV_PLAYERPHYSICS "
187 "DP_SV_POINTPARTICLES "
189 "DP_SV_PRECACHEANYTIME "
193 "DP_SV_ROTATINGBMODEL "
197 "DP_SV_SPAWNFUNC_PREFIX "
198 "DP_SV_WRITEPICTURE "
199 "DP_SV_WRITEUNTERMINATEDSTRING "
203 "DP_TE_EXPLOSIONRGB "
205 "DP_TE_PARTICLECUBE "
206 "DP_TE_PARTICLERAIN "
207 "DP_TE_PARTICLESNOW "
209 "DP_TE_QUADEFFECTS1 "
212 "DP_TE_STANDARDEFFECTBUILTINS "
213 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
217 "FTE_CSQC_SKELETONOBJECTS "
220 "KRIMZON_SV_PARSECLIENTCOMMAND "
223 "NEXUIZ_PLAYERMODEL "
225 "PRYDON_CLIENTCURSOR "
226 "TENEBRAE_GFX_DLIGHTS "
229 //"EXT_CSQC " // not ready yet
236 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.
238 setorigin (entity, origin)
241 static void VM_SV_setorigin(prvm_prog_t *prog)
245 VM_SAFEPARMCOUNT(2, VM_setorigin);
247 e = PRVM_G_EDICT(OFS_PARM0);
248 if (e == prog->edicts)
250 VM_Warning(prog, "setorigin: can not modify world entity\n");
253 if (e->priv.server->free)
255 VM_Warning(prog, "setorigin: can not modify free entity\n");
258 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), PRVM_serveredictvector(e, origin));
259 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
260 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
264 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
265 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qboolean rotate)
269 for (i=0 ; i<3 ; i++)
271 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
273 // set derived values
274 VectorCopy (min, PRVM_serveredictvector(e, mins));
275 VectorCopy (max, PRVM_serveredictvector(e, maxs));
276 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
285 the size box is rotated by the current angle
286 LordHavoc: no it isn't...
288 setsize (entity, minvector, maxvector)
291 static void VM_SV_setsize(prvm_prog_t *prog)
296 VM_SAFEPARMCOUNT(3, VM_setsize);
298 e = PRVM_G_EDICT(OFS_PARM0);
299 if (e == prog->edicts)
301 VM_Warning(prog, "setsize: can not modify world entity\n");
304 if (e->priv.server->free)
306 VM_Warning(prog, "setsize: can not modify free entity\n");
309 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), mins);
310 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), maxs);
311 SetMinMaxSize(prog, e, mins, maxs, false);
319 setmodel(entity, model)
322 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
323 static void VM_SV_setmodel(prvm_prog_t *prog)
329 VM_SAFEPARMCOUNT(2, VM_setmodel);
331 e = PRVM_G_EDICT(OFS_PARM0);
332 if (e == prog->edicts)
334 VM_Warning(prog, "setmodel: can not modify world entity\n");
337 if (e->priv.server->free)
339 VM_Warning(prog, "setmodel: can not modify free entity\n");
342 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
343 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
344 PRVM_serveredictfloat(e, modelindex) = i;
346 mod = SV_GetModelByIndex(i);
350 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
351 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
353 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
356 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
363 single print to a specific client
365 sprint(clientent, value)
368 static void VM_SV_sprint(prvm_prog_t *prog)
372 char string[VM_STRINGTEMP_LENGTH];
374 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
376 VM_VarString(prog, 1, string, sizeof(string));
378 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
379 // LordHavoc: div0 requested that sprintto world operate like print
386 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
388 VM_Warning(prog, "tried to centerprint to a non-client\n");
392 client = svs.clients + entnum-1;
393 if (!client->netconnection)
396 MSG_WriteChar(&client->netconnection->message,svc_print);
397 MSG_WriteString(&client->netconnection->message, string);
405 single print to a specific client
407 centerprint(clientent, value)
410 static void VM_SV_centerprint(prvm_prog_t *prog)
414 char string[VM_STRINGTEMP_LENGTH];
416 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
418 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
420 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
422 VM_Warning(prog, "tried to centerprint to a non-client\n");
426 client = svs.clients + entnum-1;
427 if (!client->netconnection)
430 VM_VarString(prog, 1, string, sizeof(string));
431 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
432 MSG_WriteString(&client->netconnection->message, string);
439 particle(origin, color, count)
442 static void VM_SV_particle(prvm_prog_t *prog)
448 VM_SAFEPARMCOUNT(4, VM_SV_particle);
450 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
451 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
452 color = (int)PRVM_G_FLOAT(OFS_PARM2);
453 count = (int)PRVM_G_FLOAT(OFS_PARM3);
454 SV_StartParticle (org, dir, color, count);
464 static void VM_SV_ambientsound(prvm_prog_t *prog)
468 prvm_vec_t vol, attenuation;
471 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
473 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
474 samp = PRVM_G_STRING(OFS_PARM1);
475 vol = PRVM_G_FLOAT(OFS_PARM2);
476 attenuation = PRVM_G_FLOAT(OFS_PARM3);
478 // check to see if samp was properly precached
479 soundnum = SV_SoundIndex(samp, 1);
487 // add an svc_spawnambient command to the level signon packet
490 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
492 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
494 MSG_WriteVector(&sv.signon, pos, sv.protocol);
496 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
497 MSG_WriteShort (&sv.signon, soundnum);
499 MSG_WriteByte (&sv.signon, soundnum);
501 MSG_WriteByte (&sv.signon, (int)(vol*255));
502 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
510 Each entity can have eight independant sound sources, like voice,
513 Channel 0 is an auto-allocate channel, the others override anything
514 already running on that entity/channel pair.
516 An attenuation of 0 will play full volume everywhere in the level.
517 Larger attenuations will drop off.
521 static void VM_SV_sound(prvm_prog_t *prog)
525 prvm_edict_t *entity;
531 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
533 entity = PRVM_G_EDICT(OFS_PARM0);
534 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
535 sample = PRVM_G_STRING(OFS_PARM2);
536 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
539 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
543 attenuation = PRVM_G_FLOAT(OFS_PARM4);
547 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
552 if(channel >= 8 && channel <= 15) // weird QW feature
554 flags |= CHANNELFLAG_RELIABLE;
560 // LordHavoc: we only let the qc set certain flags, others are off-limits
561 flags = (int)PRVM_G_FLOAT(OFS_PARM6) & (CHANNELFLAG_RELIABLE | CHANNELFLAG_FORCELOOP | CHANNELFLAG_PAUSED);
564 if (volume < 0 || volume > 255)
566 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
570 if (attenuation < 0 || attenuation > 4)
572 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
576 channel = CHAN_USER2ENGINE(channel);
578 if (!IS_CHAN(channel))
580 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
584 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANNELFLAG_RELIABLE, pitchchange);
591 Follows the same logic as VM_SV_sound, except instead of
592 an entity, an origin for the sound is provided, and channel
593 is omitted (since no entity is being tracked).
597 static void VM_SV_pointsound(prvm_prog_t *prog)
605 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
607 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
608 sample = PRVM_G_STRING(OFS_PARM1);
609 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
610 attenuation = PRVM_G_FLOAT(OFS_PARM3);
611 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
613 if (volume < 0 || volume > 255)
615 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
619 if (attenuation < 0 || attenuation > 4)
621 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
625 SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
632 Used for use tracing and shot targeting
633 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
634 if the tryents flag is set.
636 traceline (vector1, vector2, movetype, ignore)
639 static void VM_SV_traceline(prvm_prog_t *prog)
646 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
648 prog->xfunction->builtinsprofile += 30;
650 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
651 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), v2);
652 move = (int)PRVM_G_FLOAT(OFS_PARM2);
653 ent = PRVM_G_EDICT(OFS_PARM3);
655 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]))
656 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));
658 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent), collision_extendtracelinelength.value);
660 VM_SetTraceGlobals(prog, &trace);
668 Used for use tracing and shot targeting
669 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
670 if the tryents flag is set.
672 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
675 // LordHavoc: added this for my own use, VERY useful, similar to traceline
676 static void VM_SV_tracebox(prvm_prog_t *prog)
678 vec3_t v1, v2, m1, m2;
683 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
685 prog->xfunction->builtinsprofile += 30;
687 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
688 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), m1);
689 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), m2);
690 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), v2);
691 move = (int)PRVM_G_FLOAT(OFS_PARM4);
692 ent = PRVM_G_EDICT(OFS_PARM5);
694 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]))
695 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));
697 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent), collision_extendtraceboxlength.value);
699 VM_SetTraceGlobals(prog, &trace);
702 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
706 vec3_t move, end, tossentorigin, tossentmins, tossentmaxs;
707 vec3_t original_origin;
708 vec3_t original_velocity;
709 vec3_t original_angles;
710 vec3_t original_avelocity;
713 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
714 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
715 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
716 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
718 gravity = PRVM_serveredictfloat(tossent, gravity);
721 gravity *= sv_gravity.value * 0.025;
723 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
725 SV_CheckVelocity (tossent);
726 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
727 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
728 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
729 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
730 VectorCopy(PRVM_serveredictvector(tossent, origin), tossentorigin);
731 VectorCopy(PRVM_serveredictvector(tossent, mins), tossentmins);
732 VectorCopy(PRVM_serveredictvector(tossent, maxs), tossentmaxs);
733 trace = SV_TraceBox(tossentorigin, tossentmins, tossentmaxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent), collision_extendmovelength.value);
734 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
735 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
737 if (trace.fraction < 1)
741 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
742 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
743 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
744 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
749 static void VM_SV_tracetoss(prvm_prog_t *prog)
753 prvm_edict_t *ignore;
755 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
757 prog->xfunction->builtinsprofile += 600;
759 ent = PRVM_G_EDICT(OFS_PARM0);
760 if (ent == prog->edicts)
762 VM_Warning(prog, "tracetoss: can not use world entity\n");
765 ignore = PRVM_G_EDICT(OFS_PARM1);
767 trace = SV_Trace_Toss(prog, ent, ignore);
769 VM_SetTraceGlobals(prog, &trace);
772 //============================================================================
774 static int checkpvsbytes;
775 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
777 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
783 // cycle to the next one
785 check = bound(1, check, svs.maxclients);
786 if (check == svs.maxclients)
794 prog->xfunction->builtinsprofile++;
796 if (i == svs.maxclients+1)
798 // look up the client's edict
799 ent = PRVM_EDICT_NUM(i);
800 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
801 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
803 // found a valid client (possibly the same one again)
807 // get the PVS for the entity
808 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
810 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
811 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
820 Returns a client (or object that has a client enemy) that would be a
823 If there is more than one valid option, they are cycled each frame
825 If (self.origin + self.viewofs) is not in the PVS of the current target,
826 it is not returned at all.
831 int c_invis, c_notvis;
832 static void VM_SV_checkclient(prvm_prog_t *prog)
834 prvm_edict_t *ent, *self;
837 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
839 // find a new check if on a new frame
840 if (sv.time - sv.lastchecktime >= 0.1)
842 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
843 sv.lastchecktime = sv.time;
846 // return check if it might be visible
847 ent = PRVM_EDICT_NUM(sv.lastcheck);
848 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
850 VM_RETURN_EDICT(prog->edicts);
854 // if current entity can't possibly see the check entity, return 0
855 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
856 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
857 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
860 VM_RETURN_EDICT(prog->edicts);
864 // might be able to see it
866 VM_RETURN_EDICT(ent);
869 //============================================================================
875 Checks if an entity is in a point's PVS.
876 Should be fast but can be inexact.
878 float checkpvs(vector viewpos, entity viewee) = #240;
881 static void VM_SV_checkpvs(prvm_prog_t *prog)
883 vec3_t viewpos, absmin, absmax;
884 prvm_edict_t *viewee;
889 unsigned char fatpvs[MAX_MAP_LEAFS/8];
892 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
893 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
894 viewee = PRVM_G_EDICT(OFS_PARM1);
896 if(viewee->priv.server->free)
898 VM_Warning(prog, "checkpvs: can not check free entity\n");
899 PRVM_G_FLOAT(OFS_RETURN) = 4;
904 if(!sv.worldmodel || !sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
906 // no PVS support on this worldmodel... darn
907 PRVM_G_FLOAT(OFS_RETURN) = 3;
910 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
913 // viewpos isn't in any PVS... darn
914 PRVM_G_FLOAT(OFS_RETURN) = 2;
917 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
918 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
919 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, absmin, absmax);
921 // using fat PVS like FTEQW does (slow)
922 if(!sv.worldmodel || !sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
924 // no PVS support on this worldmodel... darn
925 PRVM_G_FLOAT(OFS_RETURN) = 3;
928 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
931 // viewpos isn't in any PVS... darn
932 PRVM_G_FLOAT(OFS_RETURN) = 2;
935 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
936 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
937 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, absmin, absmax);
946 Sends text over to the client's execution buffer
948 stuffcmd (clientent, value, ...)
951 static void VM_SV_stuffcmd(prvm_prog_t *prog)
955 char string[VM_STRINGTEMP_LENGTH];
957 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
959 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
960 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
962 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
966 VM_VarString(prog, 1, string, sizeof(string));
969 host_client = svs.clients + entnum-1;
970 Host_ClientCommands ("%s", string);
978 Returns a chain of entities that have origins within a spherical area
980 findradius (origin, radius)
983 static void VM_SV_findradius(prvm_prog_t *prog)
985 prvm_edict_t *ent, *chain;
986 vec_t radius, radius2;
987 vec3_t org, eorg, mins, maxs;
990 static prvm_edict_t *touchedicts[MAX_EDICTS];
993 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
996 chainfield = PRVM_G_INT(OFS_PARM2);
998 chainfield = prog->fieldoffsets.chain;
1000 prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
1002 chain = (prvm_edict_t *)prog->edicts;
1004 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1005 radius = PRVM_G_FLOAT(OFS_PARM1);
1006 radius2 = radius * radius;
1008 mins[0] = org[0] - (radius + 1);
1009 mins[1] = org[1] - (radius + 1);
1010 mins[2] = org[2] - (radius + 1);
1011 maxs[0] = org[0] + (radius + 1);
1012 maxs[1] = org[1] + (radius + 1);
1013 maxs[2] = org[2] + (radius + 1);
1014 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1015 if (numtouchedicts > MAX_EDICTS)
1017 // this never happens
1018 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1019 numtouchedicts = MAX_EDICTS;
1021 for (i = 0;i < numtouchedicts;i++)
1023 ent = touchedicts[i];
1024 prog->xfunction->builtinsprofile++;
1025 // Quake did not return non-solid entities but darkplaces does
1026 // (note: this is the reason you can't blow up fallen zombies)
1027 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1029 // LordHavoc: compare against bounding box rather than center so it
1030 // doesn't miss large objects, and use DotProduct instead of Length
1031 // for a major speedup
1032 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1033 if (sv_gameplayfix_findradiusdistancetobox.integer)
1035 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1036 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1037 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1040 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1041 if (DotProduct(eorg, eorg) < radius2)
1043 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1048 VM_RETURN_EDICT(chain);
1051 static void VM_SV_precache_sound(prvm_prog_t *prog)
1053 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1054 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1057 static void VM_SV_precache_model(prvm_prog_t *prog)
1059 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1060 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1061 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1068 float(float yaw, float dist[, settrace]) walkmove
1071 static void VM_SV_walkmove(prvm_prog_t *prog)
1080 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1082 // assume failure if it returns early
1083 PRVM_G_FLOAT(OFS_RETURN) = 0;
1085 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1086 if (ent == prog->edicts)
1088 VM_Warning(prog, "walkmove: can not modify world entity\n");
1091 if (ent->priv.server->free)
1093 VM_Warning(prog, "walkmove: can not modify free entity\n");
1096 yaw = PRVM_G_FLOAT(OFS_PARM0);
1097 dist = PRVM_G_FLOAT(OFS_PARM1);
1098 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1100 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1103 yaw = yaw*M_PI*2 / 360;
1105 move[0] = cos(yaw)*dist;
1106 move[1] = sin(yaw)*dist;
1109 // save program state, because SV_movestep may call other progs
1110 oldf = prog->xfunction;
1111 oldself = PRVM_serverglobaledict(self);
1113 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1116 // restore program state
1117 prog->xfunction = oldf;
1118 PRVM_serverglobaledict(self) = oldself;
1129 static void VM_SV_droptofloor(prvm_prog_t *prog)
1132 vec3_t end, entorigin, entmins, entmaxs;
1135 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1137 // assume failure if it returns early
1138 PRVM_G_FLOAT(OFS_RETURN) = 0;
1140 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1141 if (ent == prog->edicts)
1143 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1146 if (ent->priv.server->free)
1148 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1152 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1155 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1156 SV_NudgeOutOfSolid(ent);
1158 VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
1159 VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
1160 VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
1161 trace = SV_TraceBox(entorigin, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), collision_extendmovelength.value);
1162 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1165 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]);
1166 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1167 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), collision_extendmovelength.value);
1168 VectorSubtract(trace.endpos, offset, trace.endpos);
1169 if (trace.startsolid)
1171 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]);
1173 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1174 PRVM_serveredictedict(ent, groundentity) = 0;
1175 PRVM_G_FLOAT(OFS_RETURN) = 1;
1177 else if (trace.fraction < 1)
1179 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]);
1180 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1181 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1182 SV_NudgeOutOfSolid(ent);
1184 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1185 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1186 PRVM_G_FLOAT(OFS_RETURN) = 1;
1187 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1188 ent->priv.server->suspendedinairflag = true;
1193 if (!trace.allsolid && trace.fraction < 1)
1195 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1197 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1198 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1199 PRVM_G_FLOAT(OFS_RETURN) = 1;
1200 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1201 ent->priv.server->suspendedinairflag = true;
1210 void(float style, string value) lightstyle
1213 static void VM_SV_lightstyle(prvm_prog_t *prog)
1220 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1222 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1223 val = PRVM_G_STRING(OFS_PARM1);
1225 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1226 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1229 // change the string in sv
1230 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1232 // send message to all clients on this server
1233 if (sv.state != ss_active)
1236 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1238 if (client->active && client->netconnection)
1240 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1241 MSG_WriteChar (&client->netconnection->message,style);
1242 MSG_WriteString (&client->netconnection->message, val);
1252 static void VM_SV_checkbottom(prvm_prog_t *prog)
1254 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1255 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1263 static void VM_SV_pointcontents(prvm_prog_t *prog)
1266 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1267 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point);
1268 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(point));
1275 Pick a vector for the player to shoot along
1276 vector aim(entity, missilespeed)
1279 static void VM_SV_aim(prvm_prog_t *prog)
1281 prvm_edict_t *ent, *check, *bestent;
1282 vec3_t start, dir, end, bestdir;
1285 float dist, bestdist;
1288 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1290 // assume failure if it returns early
1291 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1292 // if sv_aim is so high it can't possibly accept anything, skip out early
1293 if (sv_aim.value >= 1)
1296 ent = PRVM_G_EDICT(OFS_PARM0);
1297 if (ent == prog->edicts)
1299 VM_Warning(prog, "aim: can not use world entity\n");
1302 if (ent->priv.server->free)
1304 VM_Warning(prog, "aim: can not use free entity\n");
1307 //speed = PRVM_G_FLOAT(OFS_PARM1);
1309 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1312 // try sending a trace straight
1313 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1314 VectorMA (start, 2048, dir, end);
1315 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, collision_extendmovelength.value);
1316 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1317 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1319 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1324 // try all possible entities
1325 VectorCopy (dir, bestdir);
1326 bestdist = sv_aim.value;
1329 check = PRVM_NEXT_EDICT(prog->edicts);
1330 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1332 prog->xfunction->builtinsprofile++;
1333 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1337 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1338 continue; // don't aim at teammate
1339 for (j=0 ; j<3 ; j++)
1340 end[j] = PRVM_serveredictvector(check, origin)[j]
1341 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1342 VectorSubtract (end, start, dir);
1343 VectorNormalize (dir);
1344 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1345 if (dist < bestdist)
1346 continue; // to far to turn
1347 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, collision_extendmovelength.value);
1348 if (tr.ent == check)
1349 { // can shoot at this one
1357 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1358 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1359 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1361 VectorNormalize (end);
1362 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1366 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1371 ===============================================================================
1375 ===============================================================================
1378 #define MSG_BROADCAST 0 // unreliable to all
1379 #define MSG_ONE 1 // reliable to one (msg_entity)
1380 #define MSG_ALL 2 // reliable to all
1381 #define MSG_INIT 3 // write to the init string
1382 #define MSG_ENTITY 5
1384 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1390 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1394 return &sv.datagram;
1397 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1398 entnum = PRVM_NUM_FOR_EDICT(ent);
1399 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1401 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1402 return &sv.reliable_datagram;
1405 return &svs.clients[entnum-1].netconnection->message;
1408 VM_Warning(prog, "WriteDest: bad destination\n");
1410 return &sv.reliable_datagram;
1416 return sv.writeentitiestoclient_msg;
1422 static void VM_SV_WriteByte(prvm_prog_t *prog)
1424 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1425 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1428 static void VM_SV_WriteChar(prvm_prog_t *prog)
1430 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1431 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1434 static void VM_SV_WriteShort(prvm_prog_t *prog)
1436 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1437 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1440 static void VM_SV_WriteLong(prvm_prog_t *prog)
1442 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1443 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1446 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1448 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1449 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1452 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1454 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1455 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1458 static void VM_SV_WriteString(prvm_prog_t *prog)
1460 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1461 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1464 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1466 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1467 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1471 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1473 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1474 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1477 // writes a picture as at most size bytes of data
1479 // IMGNAME \0 SIZE(short) IMGDATA
1480 // if failed to read/compress:
1482 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1483 static void VM_SV_WritePicture(prvm_prog_t *prog)
1485 const char *imgname;
1489 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1491 imgname = PRVM_G_STRING(OFS_PARM1);
1492 size = (size_t) PRVM_G_FLOAT(OFS_PARM2);
1496 MSG_WriteString(WriteDest(prog), imgname);
1497 if(Image_Compress(imgname, size, &buf, &size))
1500 MSG_WriteShort(WriteDest(prog), (int)size);
1501 SZ_Write(WriteDest(prog), (unsigned char *) buf, (int)size);
1506 MSG_WriteShort(WriteDest(prog), 0);
1510 //////////////////////////////////////////////////////////
1512 static void VM_SV_makestatic(prvm_prog_t *prog)
1517 // allow 0 parameters due to an id1 qc bug in which this function is used
1518 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1519 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1521 if (prog->argc >= 1)
1522 ent = PRVM_G_EDICT(OFS_PARM0);
1524 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1525 if (ent == prog->edicts)
1527 VM_Warning(prog, "makestatic: can not modify world entity\n");
1530 if (ent->priv.server->free)
1532 VM_Warning(prog, "makestatic: can not modify free entity\n");
1537 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1542 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1543 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1544 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1546 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1548 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1549 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1550 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1554 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1555 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1556 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1559 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1560 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1561 for (i=0 ; i<3 ; i++)
1563 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1564 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1567 // throw the entity away now
1568 PRVM_ED_Free(prog, ent);
1571 //=============================================================================
1578 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1584 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1586 ent = PRVM_G_EDICT(OFS_PARM0);
1587 i = PRVM_NUM_FOR_EDICT(ent);
1588 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1590 Con_Print("tried to setspawnparms on a non-client\n");
1594 // copy spawn parms out of the client_t
1595 client = svs.clients + i-1;
1596 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1597 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1604 Returns a color vector indicating the lighting at the requested point.
1606 (Internal Operation note: actually measures the light beneath the point, just like
1607 the model lighting on the client)
1612 static void VM_SV_getlight(prvm_prog_t *prog)
1614 vec3_t ambientcolor, diffusecolor, diffusenormal;
1616 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1617 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
1618 VectorClear(ambientcolor);
1619 VectorClear(diffusecolor);
1620 VectorClear(diffusenormal);
1621 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1622 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1623 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1628 unsigned char type; // 1/2/8 or other value if isn't used
1632 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1633 static int vm_customstats_last;
1635 void VM_CustomStats_Clear (void)
1639 Z_Free(vm_customstats);
1640 vm_customstats = NULL;
1641 vm_customstats_last = -1;
1645 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1647 prvm_prog_t *prog = SVVM_prog;
1654 for(i=0; i<vm_customstats_last+1 ;i++)
1656 if(!vm_customstats[i].type)
1658 switch(vm_customstats[i].type)
1660 //string as 16 bytes
1663 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1664 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1665 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1666 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1667 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1669 //float field sent as-is
1671 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1673 //integer value of float field
1675 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1683 // void(float index, float type, .void field) SV_AddStat = #232;
1684 // Set up an auto-sent player stat.
1685 // Client's get thier own fields sent to them. Index may not be less than 32.
1686 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1687 // 1: string (4 stats carrying a total of 16 charactures)
1688 // 2: float (one stat, float converted to an integer for transportation)
1689 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1690 static void VM_SV_AddStat(prvm_prog_t *prog)
1695 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1699 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1702 VM_Warning(prog, "PF_SV_AddStat: not enough memory\n");
1706 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1707 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1708 off = PRVM_G_INT (OFS_PARM2);
1713 VM_Warning(prog, "PF_SV_AddStat: index may not be less than 32\n");
1716 if(i >= (MAX_CL_STATS-32))
1718 VM_Warning(prog, "PF_SV_AddStat: index >= MAX_CL_STATS\n");
1721 if(i > (MAX_CL_STATS-32-4) && type == 1)
1723 VM_Warning(prog, "PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1726 vm_customstats[i].type = type;
1727 vm_customstats[i].fieldoffset = off;
1728 if(vm_customstats_last < i)
1729 vm_customstats_last = i;
1736 copies data from one entity to another
1738 copyentity(src, dst)
1741 static void VM_SV_copyentity(prvm_prog_t *prog)
1743 prvm_edict_t *in, *out;
1744 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1745 in = PRVM_G_EDICT(OFS_PARM0);
1746 if (in == prog->edicts)
1748 VM_Warning(prog, "copyentity: can not read world entity\n");
1751 if (in->priv.server->free)
1753 VM_Warning(prog, "copyentity: can not read free entity\n");
1756 out = PRVM_G_EDICT(OFS_PARM1);
1757 if (out == prog->edicts)
1759 VM_Warning(prog, "copyentity: can not modify world entity\n");
1762 if (out->priv.server->free)
1764 VM_Warning(prog, "copyentity: can not modify free entity\n");
1767 memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
1776 sets the color of a client and broadcasts the update to all connected clients
1778 setcolor(clientent, value)
1781 static void VM_SV_setcolor(prvm_prog_t *prog)
1786 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1787 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1788 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1790 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1792 Con_Print("tried to setcolor a non-client\n");
1796 client = svs.clients + entnum-1;
1799 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1800 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1803 if (client->old_colors != client->colors)
1805 client->old_colors = client->colors;
1806 // send notification to all clients
1807 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1808 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1809 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1817 effect(origin, modelname, startframe, framecount, framerate)
1820 static void VM_SV_effect(prvm_prog_t *prog)
1825 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1826 s = PRVM_G_STRING(OFS_PARM1);
1829 VM_Warning(prog, "effect: no model specified\n");
1833 i = SV_ModelIndex(s, 1);
1836 VM_Warning(prog, "effect: model not precached\n");
1840 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1842 VM_Warning(prog, "effect: framecount < 1\n");
1846 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1848 VM_Warning(prog, "effect: framerate < 1\n");
1852 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1853 SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1856 static void VM_SV_te_blood(prvm_prog_t *prog)
1858 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1859 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1861 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1862 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1864 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1865 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1866 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1868 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1869 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1870 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1872 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1873 SV_FlushBroadcastMessages();
1876 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1878 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1879 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1881 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1882 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1884 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1885 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1886 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1888 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1889 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1890 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1892 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1894 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1895 SV_FlushBroadcastMessages();
1898 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1900 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1901 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1902 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1908 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1909 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1910 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1911 SV_FlushBroadcastMessages();
1914 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1916 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1917 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1919 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1920 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1922 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1923 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1924 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1926 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1934 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1936 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1937 // gravity true/false
1938 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1941 SV_FlushBroadcastMessages();
1944 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1946 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1947 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1949 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1950 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1952 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1953 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1954 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1964 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1966 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1967 SV_FlushBroadcastMessages();
1970 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1972 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1973 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1975 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1976 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1978 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1979 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1980 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1983 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1984 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1990 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1992 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1993 SV_FlushBroadcastMessages();
1996 static void VM_SV_te_spark(prvm_prog_t *prog)
1998 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1999 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2001 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2002 MSG_WriteByte(&sv.datagram, TE_SPARK);
2004 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2005 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2006 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2008 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2009 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2010 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2012 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2013 SV_FlushBroadcastMessages();
2016 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2018 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2019 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2020 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2022 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2023 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2024 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2025 SV_FlushBroadcastMessages();
2028 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2030 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2031 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2032 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2034 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2035 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2036 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2037 SV_FlushBroadcastMessages();
2040 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2042 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2043 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2044 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2046 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2047 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2048 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2049 SV_FlushBroadcastMessages();
2052 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2054 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2055 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2056 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2058 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2059 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2060 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2061 SV_FlushBroadcastMessages();
2064 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2066 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2067 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2068 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2070 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2071 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2072 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2073 SV_FlushBroadcastMessages();
2076 static void VM_SV_te_customflash(prvm_prog_t *prog)
2078 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2079 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2081 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2082 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2084 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2085 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2086 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2088 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2090 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2092 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2093 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2094 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2095 SV_FlushBroadcastMessages();
2098 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2100 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2101 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2102 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2104 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2105 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2106 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2107 SV_FlushBroadcastMessages();
2110 static void VM_SV_te_spike(prvm_prog_t *prog)
2112 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2113 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2114 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2116 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2117 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2118 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2119 SV_FlushBroadcastMessages();
2122 static void VM_SV_te_superspike(prvm_prog_t *prog)
2124 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2125 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2126 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2128 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2129 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2130 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2131 SV_FlushBroadcastMessages();
2134 static void VM_SV_te_explosion(prvm_prog_t *prog)
2136 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2137 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2138 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2140 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2141 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2142 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2143 SV_FlushBroadcastMessages();
2146 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2148 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2149 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2150 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2152 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2153 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2154 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2155 SV_FlushBroadcastMessages();
2158 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2160 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2161 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2162 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2164 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2165 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2166 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2167 SV_FlushBroadcastMessages();
2170 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2172 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2173 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2174 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2176 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2177 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2178 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2179 SV_FlushBroadcastMessages();
2182 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2184 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2185 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2186 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2188 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2189 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2190 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2191 SV_FlushBroadcastMessages();
2194 static void VM_SV_te_teleport(prvm_prog_t *prog)
2196 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2197 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2198 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2200 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2201 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2202 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2203 SV_FlushBroadcastMessages();
2206 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2208 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2209 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2210 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2212 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2213 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2214 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2216 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2217 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2218 SV_FlushBroadcastMessages();
2221 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2223 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2224 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2225 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2227 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2230 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2231 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2234 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2235 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2236 SV_FlushBroadcastMessages();
2239 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2241 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2242 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2243 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2245 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2247 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2248 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2249 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2251 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2252 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2253 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2254 SV_FlushBroadcastMessages();
2257 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2259 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2260 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2261 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2263 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2265 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2266 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2267 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2269 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2270 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2271 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2272 SV_FlushBroadcastMessages();
2275 static void VM_SV_te_beam(prvm_prog_t *prog)
2277 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2278 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2279 MSG_WriteByte(&sv.datagram, TE_BEAM);
2281 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2283 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2284 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2285 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2287 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2288 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2289 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2290 SV_FlushBroadcastMessages();
2293 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2295 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2296 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2297 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2298 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2299 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2300 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2301 SV_FlushBroadcastMessages();
2304 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2306 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2307 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2308 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2310 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2311 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2312 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2314 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2315 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2316 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2318 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2319 SV_FlushBroadcastMessages();
2322 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2323 //this function originally written by KrimZon, made shorter by LordHavoc
2324 static void VM_SV_clientcommand(prvm_prog_t *prog)
2326 client_t *temp_client;
2328 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2330 //find client for this entity
2331 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2332 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2334 Con_Print("PF_clientcommand: entity is not a client\n");
2338 temp_client = host_client;
2339 host_client = svs.clients + i;
2340 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
2341 host_client = temp_client;
2344 //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)
2345 static void VM_SV_setattachment(prvm_prog_t *prog)
2347 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2348 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2349 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2352 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2354 if (e == prog->edicts)
2356 VM_Warning(prog, "setattachment: can not modify world entity\n");
2359 if (e->priv.server->free)
2361 VM_Warning(prog, "setattachment: can not modify free entity\n");
2365 if (tagentity == NULL)
2366 tagentity = prog->edicts;
2370 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2372 model = SV_GetModelFromEdict(tagentity);
2375 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2377 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);
2380 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));
2383 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2384 PRVM_serveredictfloat(e, tag_index) = tagindex;
2387 /////////////////////////////////////////
2388 // DP_MD3_TAGINFO extension coded by VorteX
2390 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2394 i = (int)PRVM_serveredictfloat(e, modelindex);
2395 if (i < 1 || i >= MAX_MODELS)
2398 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2401 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2408 Matrix4x4_CreateIdentity(tag_localmatrix);
2410 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2412 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2423 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2426 float pitchsign = 1;
2428 scale = PRVM_serveredictfloat(ent, scale);
2433 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);
2436 pitchsign = SV_GetPitchSign(prog, ent);
2437 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);
2441 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2444 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2446 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2447 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2448 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2449 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2451 *out = identitymatrix;
2455 // Warnings/errors code:
2456 // 0 - normal (everything all-right)
2459 // 3 - null or non-precached model
2460 // 4 - no tags with requested index
2461 // 5 - runaway loop at attachment chain
2462 extern cvar_t cl_bob;
2463 extern cvar_t cl_bobcycle;
2464 extern cvar_t cl_bobup;
2465 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2468 int modelindex, attachloop;
2469 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2472 *out = identitymatrix; // warnings and errors return identical matrix
2474 if (ent == prog->edicts)
2476 if (ent->priv.server->free)
2479 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2480 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2483 model = SV_GetModelByIndex(modelindex);
2485 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2486 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2487 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2489 tagmatrix = identitymatrix;
2490 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2494 if (attachloop >= 256) // prevent runaway looping
2496 // apply transformation by child's tagindex on parent entity and then
2497 // by parent entity itself
2498 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2499 if (ret && attachloop == 0)
2501 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2502 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2503 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2504 // next iteration we process the parent entity
2505 if (PRVM_serveredictedict(ent, tag_entity))
2507 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2508 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2515 // RENDER_VIEWMODEL magic
2516 if (PRVM_serveredictedict(ent, viewmodelforclient))
2518 Matrix4x4_Copy(&tagmatrix, out);
2519 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2521 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2522 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2525 // Cl_bob, ported from rendering code
2526 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2529 // LordHavoc: this code is *weird*, but not replacable (I think it
2530 // should be done in QC on the server, but oh well, quake is quake)
2531 // LordHavoc: figured out bobup: the time at which the sin is at 180
2532 // degrees (which allows lengthening or squishing the peak or valley)
2533 cycle = sv.time/cl_bobcycle.value;
2534 cycle -= (int)cycle;
2535 if (cycle < cl_bobup.value)
2536 cycle = sin(M_PI * cycle / cl_bobup.value);
2538 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2539 // bob is proportional to velocity in the xy plane
2540 // (don't count Z, or jumping messes it up)
2541 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;
2542 bob = bob*0.3 + bob*0.7*cycle;
2543 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2550 //float(entity ent, string tagname) gettagindex;
2552 static void VM_SV_gettagindex(prvm_prog_t *prog)
2555 const char *tag_name;
2558 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2560 ent = PRVM_G_EDICT(OFS_PARM0);
2561 tag_name = PRVM_G_STRING(OFS_PARM1);
2563 if (ent == prog->edicts)
2565 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2568 if (ent->priv.server->free)
2570 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2575 if (!SV_GetModelFromEdict(ent))
2576 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2579 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2581 if(developer_extra.integer)
2582 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2584 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2587 //vector(entity ent, float tagindex) gettaginfo;
2588 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2592 matrix4x4_t tag_matrix;
2593 matrix4x4_t tag_localmatrix;
2595 const char *tagname;
2597 vec3_t forward, left, up, origin;
2598 const dp_model_t *model;
2600 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2602 e = PRVM_G_EDICT(OFS_PARM0);
2603 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2605 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2606 Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
2607 VectorCopy(forward, PRVM_serverglobalvector(v_forward));
2608 VectorNegate(left, PRVM_serverglobalvector(v_right));
2609 VectorCopy(up, PRVM_serverglobalvector(v_up));
2610 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2611 model = SV_GetModelFromEdict(e);
2612 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2613 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2614 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2615 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2616 Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
2618 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2619 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2620 VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
2621 VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
2622 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2623 VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset));
2628 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2631 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2634 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2637 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2640 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2645 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2646 static void VM_SV_dropclient(prvm_prog_t *prog)
2649 client_t *oldhostclient;
2650 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2651 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2652 if (clientnum < 0 || clientnum >= svs.maxclients)
2654 VM_Warning(prog, "dropclient: not a client\n");
2657 if (!svs.clients[clientnum].active)
2659 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2662 oldhostclient = host_client;
2663 host_client = svs.clients + clientnum;
2664 SV_DropClient(false);
2665 host_client = oldhostclient;
2668 //entity() spawnclient (DP_SV_BOTCLIENT)
2669 static void VM_SV_spawnclient(prvm_prog_t *prog)
2673 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2674 prog->xfunction->builtinsprofile += 2;
2676 for (i = 0;i < svs.maxclients;i++)
2678 if (!svs.clients[i].active)
2680 prog->xfunction->builtinsprofile += 100;
2681 SV_ConnectClient (i, NULL);
2682 // this has to be set or else ClientDisconnect won't be called
2683 // we assume the qc will call ClientConnect...
2684 svs.clients[i].clientconnectcalled = true;
2685 ed = PRVM_EDICT_NUM(i + 1);
2689 VM_RETURN_EDICT(ed);
2692 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2693 static void VM_SV_clienttype(prvm_prog_t *prog)
2696 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2697 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2698 if (clientnum < 0 || clientnum >= svs.maxclients)
2699 PRVM_G_FLOAT(OFS_RETURN) = 3;
2700 else if (!svs.clients[clientnum].active)
2701 PRVM_G_FLOAT(OFS_RETURN) = 0;
2702 else if (svs.clients[clientnum].netconnection)
2703 PRVM_G_FLOAT(OFS_RETURN) = 1;
2705 PRVM_G_FLOAT(OFS_RETURN) = 2;
2712 string(string key) serverkey
2715 static void VM_SV_serverkey(prvm_prog_t *prog)
2717 char string[VM_STRINGTEMP_LENGTH];
2718 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2719 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2720 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2723 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2724 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2729 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2731 e = PRVM_G_EDICT(OFS_PARM0);
2732 if (e == prog->edicts)
2734 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2737 if (e->priv.server->free)
2739 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2742 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2743 if (i <= 0 || i >= MAX_MODELS)
2745 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2748 if (!sv.model_precache[i][0])
2750 VM_Warning(prog, "setmodelindex: model not precached\n");
2754 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2755 PRVM_serveredictfloat(e, modelindex) = i;
2757 mod = SV_GetModelByIndex(i);
2761 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2762 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2764 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2767 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2770 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2771 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2774 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2776 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2778 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2779 if (i <= 0 || i >= MAX_MODELS)
2781 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2784 if (!sv.model_precache[i][0])
2786 VM_Warning(prog, "modelnameforindex: model not precached\n");
2790 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2793 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2794 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2797 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2798 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2801 PRVM_G_FLOAT(OFS_RETURN) = i;
2804 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2805 static void VM_SV_trailparticles(prvm_prog_t *prog)
2808 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2810 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2813 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2814 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2815 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2816 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start);
2817 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end);
2818 MSG_WriteVector(&sv.datagram, start, sv.protocol);
2819 MSG_WriteVector(&sv.datagram, end, sv.protocol);
2820 SV_FlushBroadcastMessages();
2823 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2824 static void VM_SV_pointparticles(prvm_prog_t *prog)
2826 int effectnum, count;
2828 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2830 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2833 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2834 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2835 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2836 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2837 if (count == 1 && !VectorLength2(vel))
2840 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2841 MSG_WriteShort(&sv.datagram, effectnum);
2842 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2846 // 1+2+12+12+2=29 bytes
2847 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2848 MSG_WriteShort(&sv.datagram, effectnum);
2849 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2850 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2851 MSG_WriteShort(&sv.datagram, count);
2854 SV_FlushBroadcastMessages();
2857 //PF_setpause, // void(float pause) setpause = #531;
2858 static void VM_SV_setpause(prvm_prog_t *prog) {
2860 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2861 if (pauseValue != 0) { //pause the game
2863 sv.pausedstart = realtime;
2864 } else { //disable pause, in case it was enabled
2865 if (sv.paused != 0) {
2870 // send notification to all clients
2871 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2872 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2875 // #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.
2876 static void VM_SV_skel_create(prvm_prog_t *prog)
2878 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2879 dp_model_t *model = SV_GetModelByIndex(modelindex);
2880 skeleton_t *skeleton;
2882 PRVM_G_FLOAT(OFS_RETURN) = 0;
2883 if (!model || !model->num_bones)
2885 for (i = 0;i < MAX_EDICTS;i++)
2886 if (!prog->skeletons[i])
2888 if (i == MAX_EDICTS)
2890 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(prog->progs_mempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2891 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2892 skeleton->model = model;
2893 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2894 // initialize to identity matrices
2895 for (i = 0;i < skeleton->model->num_bones;i++)
2896 skeleton->relativetransforms[i] = identitymatrix;
2899 // #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
2900 static void VM_SV_skel_build(prvm_prog_t *prog)
2902 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2903 skeleton_t *skeleton;
2904 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2905 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2906 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2907 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2908 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2909 dp_model_t *model = SV_GetModelByIndex(modelindex);
2913 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2914 frameblend_t frameblend[MAX_FRAMEBLENDS];
2915 matrix4x4_t bonematrix;
2917 PRVM_G_FLOAT(OFS_RETURN) = 0;
2918 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2920 firstbone = max(0, firstbone);
2921 lastbone = min(lastbone, model->num_bones - 1);
2922 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2923 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2924 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time);
2925 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2927 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2929 memset(&bonematrix, 0, sizeof(bonematrix));
2930 for (blendindex = 0;blendindex < numblends;blendindex++)
2932 Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2933 Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp);
2935 Matrix4x4_Normalize3(&bonematrix, &bonematrix);
2936 Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac);
2938 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2941 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2942 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
2944 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2945 skeleton_t *skeleton;
2946 PRVM_G_FLOAT(OFS_RETURN) = 0;
2947 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2949 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2952 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2953 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
2955 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2956 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2957 skeleton_t *skeleton;
2958 PRVM_G_INT(OFS_RETURN) = 0;
2959 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2961 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2963 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
2966 // #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)
2967 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
2969 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2970 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2971 skeleton_t *skeleton;
2972 PRVM_G_FLOAT(OFS_RETURN) = 0;
2973 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2975 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2977 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2980 // #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
2981 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
2983 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2984 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2985 skeleton_t *skeleton;
2986 PRVM_G_FLOAT(OFS_RETURN) = 0;
2987 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2989 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2992 // #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)
2993 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
2995 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2996 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2997 skeleton_t *skeleton;
2999 vec3_t forward, left, up, origin;
3000 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3001 VectorClear(PRVM_clientglobalvector(v_forward));
3002 VectorClear(PRVM_clientglobalvector(v_right));
3003 VectorClear(PRVM_clientglobalvector(v_up));
3004 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3006 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3008 matrix = skeleton->relativetransforms[bonenum];
3009 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3010 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3011 VectorNegate(left, PRVM_clientglobalvector(v_right));
3012 VectorCopy(up, PRVM_clientglobalvector(v_up));
3013 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3016 // #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)
3017 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
3019 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3020 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3021 skeleton_t *skeleton;
3024 vec3_t forward, left, up, origin;
3025 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3026 VectorClear(PRVM_clientglobalvector(v_forward));
3027 VectorClear(PRVM_clientglobalvector(v_right));
3028 VectorClear(PRVM_clientglobalvector(v_up));
3029 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3031 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3033 matrix = skeleton->relativetransforms[bonenum];
3034 // convert to absolute
3035 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3038 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3040 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3041 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3042 VectorNegate(left, PRVM_clientglobalvector(v_right));
3043 VectorCopy(up, PRVM_clientglobalvector(v_up));
3044 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3047 // #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)
3048 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3050 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3051 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3052 vec3_t forward, left, up, origin;
3053 skeleton_t *skeleton;
3055 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3057 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3059 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3060 VectorNegate(PRVM_clientglobalvector(v_right), left);
3061 VectorCopy(PRVM_clientglobalvector(v_up), up);
3062 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3063 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3064 skeleton->relativetransforms[bonenum] = matrix;
3067 // #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)
3068 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3070 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3071 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3072 vec3_t forward, left, up, origin;
3073 skeleton_t *skeleton;
3076 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3078 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3080 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3081 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3082 VectorNegate(PRVM_clientglobalvector(v_right), left);
3083 VectorCopy(PRVM_clientglobalvector(v_up), up);
3084 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3085 temp = skeleton->relativetransforms[bonenum];
3086 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3089 // #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)
3090 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3092 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3093 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3094 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3096 vec3_t forward, left, up, origin;
3097 skeleton_t *skeleton;
3100 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3102 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3103 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3104 VectorNegate(PRVM_clientglobalvector(v_right), left);
3105 VectorCopy(PRVM_clientglobalvector(v_up), up);
3106 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3107 firstbone = max(0, firstbone);
3108 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3109 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3111 temp = skeleton->relativetransforms[bonenum];
3112 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3116 // #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
3117 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3119 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3120 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3121 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3122 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3124 skeleton_t *skeletondst;
3125 skeleton_t *skeletonsrc;
3126 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3128 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3130 firstbone = max(0, firstbone);
3131 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3132 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3133 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3134 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3137 // #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)
3138 static void VM_SV_skel_delete(prvm_prog_t *prog)
3140 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3141 skeleton_t *skeleton;
3142 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3145 prog->skeletons[skeletonindex] = NULL;
3148 // #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
3149 static void VM_SV_frameforname(prvm_prog_t *prog)
3151 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3152 dp_model_t *model = SV_GetModelByIndex(modelindex);
3153 const char *name = PRVM_G_STRING(OFS_PARM1);
3155 PRVM_G_FLOAT(OFS_RETURN) = -1;
3156 if (!model || !model->animscenes)
3158 for (i = 0;i < model->numframes;i++)
3160 if (!strcasecmp(model->animscenes[i].name, name))
3162 PRVM_G_FLOAT(OFS_RETURN) = i;
3168 // #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.
3169 static void VM_SV_frameduration(prvm_prog_t *prog)
3171 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3172 dp_model_t *model = SV_GetModelByIndex(modelindex);
3173 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3174 PRVM_G_FLOAT(OFS_RETURN) = 0;
3175 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3177 if (model->animscenes[framenum].framerate)
3178 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3182 prvm_builtin_t vm_sv_builtins[] = {
3183 NULL, // #0 NULL function (not callable) (QUAKE)
3184 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3185 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3186 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3187 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3188 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3189 VM_break, // #6 void() break (QUAKE)
3190 VM_random, // #7 float() random (QUAKE)
3191 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3192 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3193 VM_error, // #10 void(string e) error (QUAKE)
3194 VM_objerror, // #11 void(string e) objerror (QUAKE)
3195 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3196 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3197 VM_spawn, // #14 entity() spawn (QUAKE)
3198 VM_remove, // #15 void(entity e) remove (QUAKE)
3199 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3200 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3201 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3202 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3203 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3204 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3205 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3206 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3207 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3208 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3209 VM_ftos, // #26 string(float f) ftos (QUAKE)
3210 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3211 VM_coredump, // #28 void() coredump (QUAKE)
3212 VM_traceon, // #29 void() traceon (QUAKE)
3213 VM_traceoff, // #30 void() traceoff (QUAKE)
3214 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3215 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3216 NULL, // #33 (QUAKE)
3217 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3218 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3219 VM_rint, // #36 float(float v) rint (QUAKE)
3220 VM_floor, // #37 float(float v) floor (QUAKE)
3221 VM_ceil, // #38 float(float v) ceil (QUAKE)
3222 NULL, // #39 (QUAKE)
3223 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3224 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3225 NULL, // #42 (QUAKE)
3226 VM_fabs, // #43 float(float f) fabs (QUAKE)
3227 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3228 VM_cvar, // #45 float(string s) cvar (QUAKE)
3229 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3230 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3231 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3232 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3233 NULL, // #50 (QUAKE)
3234 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3235 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3236 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3237 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3238 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3239 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3240 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3241 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3242 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3243 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3244 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3245 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3246 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3247 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3248 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3249 NULL, // #66 (QUAKE)
3250 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3251 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3252 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3253 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3254 NULL, // #71 (QUAKE)
3255 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3256 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3257 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3258 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3259 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3260 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3261 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3262 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3263 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3264 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3265 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3266 NULL, // #83 (QUAKE)
3267 NULL, // #84 (QUAKE)
3268 NULL, // #85 (QUAKE)
3269 NULL, // #86 (QUAKE)
3270 NULL, // #87 (QUAKE)
3271 NULL, // #88 (QUAKE)
3272 NULL, // #89 (QUAKE)
3273 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3274 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3275 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3276 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3277 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3278 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3279 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3280 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3281 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3282 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3283 // FrikaC and Telejano range #100-#199
3294 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3295 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3296 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3297 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3298 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3299 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3300 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3301 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3302 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3303 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3384 // FTEQW range #200-#299
3403 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3406 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3407 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3408 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3409 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3410 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3411 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3412 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3413 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3414 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3415 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3417 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3425 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3448 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.
3449 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
3450 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3451 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3452 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)
3453 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
3454 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)
3455 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)
3456 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)
3457 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)
3458 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)
3459 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
3460 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)
3461 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
3462 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.
3485 // CSQC range #300-#399
3486 NULL, // #300 void() clearscene (EXT_CSQC)
3487 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3488 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3489 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3490 NULL, // #304 void() renderscene (EXT_CSQC)
3491 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3492 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3493 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3494 NULL, // #308 void() R_EndPolygon
3496 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3497 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3501 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3502 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3503 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3504 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3505 NULL, // #319 void(string name) freepic (EXT_CSQC)
3506 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3507 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3508 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3509 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3510 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3511 NULL, // #325 void(void) drawresetcliparea
3516 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3517 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3518 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3519 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3520 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3521 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3522 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3523 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3524 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3525 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3526 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3527 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3528 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3529 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3530 NULL, // #344 vector() getmousepos (EXT_CSQC)
3531 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3532 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3533 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3534 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3535 NULL, // #349 float() isdemo (EXT_CSQC)
3536 VM_isserver, // #350 float() isserver (EXT_CSQC)
3537 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3538 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3539 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3540 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3546 NULL, // #360 float() readbyte (EXT_CSQC)
3547 NULL, // #361 float() readchar (EXT_CSQC)
3548 NULL, // #362 float() readshort (EXT_CSQC)
3549 NULL, // #363 float() readlong (EXT_CSQC)
3550 NULL, // #364 float() readcoord (EXT_CSQC)
3551 NULL, // #365 float() readangle (EXT_CSQC)
3552 NULL, // #366 string() readstring (EXT_CSQC)
3553 NULL, // #367 float() readfloat (EXT_CSQC)
3586 // LordHavoc's range #400-#499
3587 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3588 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3589 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3590 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3591 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3592 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3593 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3594 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3595 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)
3596 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3597 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3598 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3599 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3600 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3601 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3602 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3603 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3604 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3605 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3606 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3607 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3608 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3609 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3610 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3611 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3612 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3613 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3614 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3615 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3616 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3617 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3618 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3619 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3620 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3621 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3622 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3623 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3624 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3625 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3626 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3627 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3628 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3629 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3630 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3631 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3632 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3633 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3634 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3635 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3636 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3637 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3638 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3639 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3640 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3641 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3642 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3643 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3644 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3646 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3647 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3648 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3649 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3650 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3651 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3652 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3653 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3654 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3655 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3656 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3658 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3659 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3660 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3661 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3662 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3663 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3664 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3665 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3666 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3667 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3668 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3669 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3670 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3671 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3672 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3673 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3681 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3682 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3683 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3684 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3685 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3686 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3687 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3688 VM_SV_WritePicture, // #501
3690 VM_whichpack, // #503 string(string) whichpack = #503;
3697 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3698 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3699 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3700 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)
3701 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3702 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3703 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3704 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3705 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3706 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3716 VM_loadfromdata, // #529
3717 VM_loadfromfile, // #530
3718 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3720 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3721 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3722 VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP)
3723 VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP)
3724 VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP)
3725 VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP)
3727 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3728 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3729 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3792 VM_callfunction, // #605
3793 VM_writetofile, // #606
3794 VM_isfunction, // #607
3800 VM_parseentitydata, // #613
3811 VM_SV_getextresponse, // #624 string getextresponse(void)
3814 VM_sprintf, // #627 string sprintf(string format, ...)
3815 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3816 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3826 VM_digest_hex, // #639
3829 VM_coverage, // #642
3833 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3835 void SVVM_init_cmd(prvm_prog_t *prog)
3840 void SVVM_reset_cmd(prvm_prog_t *prog)
3842 World_End(&sv.world);
3844 if(prog->loaded && PRVM_serverfunction(SV_Shutdown))
3846 func_t s = PRVM_serverfunction(SV_Shutdown);
3847 PRVM_serverglobalfloat(time) = sv.time;
3848 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3849 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");