6 //============================================================================
11 const char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
25 "DP_CSQC_ENTITYWORLDOBJECT "
26 "DP_CSQC_ENTITYMODELLIGHT "
27 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
29 "DP_CSQC_MINFPS_QUALITY "
30 "DP_CSQC_MULTIFRAME_INTERPOLATION "
31 "DP_CSQC_BOXPARTICLES "
32 "DP_CSQC_SPAWNPARTICLE "
33 "DP_CSQC_QUERYRENDERENTITY "
34 "DP_CSQC_ROTATEMOVES "
36 "DP_CSQC_V_CALCREFDEF_WIP1 "
37 "DP_CSQC_V_CALCREFDEF_WIP2 "
41 "DP_EF_DYNAMICMODELLIGHT "
50 "DP_EF_RESTARTANIM_BIT "
55 "DP_ENT_CUSTOMCOLORMAP "
56 "DP_ENT_EXTERIORMODELTOCLIENT "
59 "DP_ENT_LOWPRECISION "
61 "DP_ENT_TRAILEFFECTNUM "
63 "DP_GFX_EXTERNALTEXTURES "
64 "DP_GFX_EXTERNALTEXTURES_PERMAP "
66 "DP_GFX_MODEL_INTERPOLATION "
67 "DP_GFX_QUAKE3MODELTAGS "
71 "DP_GFX_FONTS_FREETYPE "
73 "DP_FONT_VARIABLEWIDTH "
75 "DP_HALFLIFE_MAP_CVAR "
78 "DP_LIGHTSTYLE_STATICVALUE "
82 "DP_MOVETYPEBOUNCEMISSILE "
83 "DP_MOVETYPEFLYWORLDONLY "
86 "DP_QC_ASINACOSATANATAN2TAN "
92 "DP_QC_CVAR_DEFSTRING "
93 "DP_QC_CVAR_DESCRIPTION "
97 "DP_QC_DIGEST_SHA256 "
100 "DP_QC_ENTITYSTRING "
102 "DP_QC_EXTRESPONSEPACKET "
104 "DP_QC_FINDCHAINFLAGS "
105 "DP_QC_FINDCHAINFLOAT "
106 "DP_QC_FINDCHAIN_TOFIELD "
112 "DP_QC_GETSURFACETRIANGLE "
113 "DP_QC_GETSURFACEPOINTATTRIBUTE "
115 "DP_QC_GETTAGINFO_BONEPROPERTIES "
117 "DP_QC_GETTIME_CDTRACK "
121 "DP_QC_MULTIPLETEMPSTRINGS "
122 "DP_QC_NUM_FOR_EDICT "
124 "DP_QC_SINCOSSQRTPOW "
127 "DP_QC_STRINGBUFFERS "
128 "DP_QC_STRINGBUFFERS_CVARLIST "
129 "DP_QC_STRINGBUFFERS_EXT_WIP "
130 "DP_QC_STRINGCOLORFUNCTIONS "
131 "DP_QC_STRING_CASE_FUNCTIONS "
133 "DP_QC_TOKENIZEBYSEPARATOR "
134 "DP_QC_TOKENIZE_CONSOLE "
137 "DP_QC_TRACE_MOVETYPE_HITMODEL "
138 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
139 "DP_QC_UNLIMITEDTEMPSTRINGS "
143 "DP_QC_VECTOANGLES_WITH_ROLL "
144 "DP_QC_VECTORVECTORS "
151 "DP_SKELETONOBJECTS "
152 "DP_SND_DIRECTIONLESSATTNNONE "
154 "DP_SND_SOUND7_WIP1 "
155 "DP_SND_SOUND7_WIP2 "
159 "DP_SND_GETSOUNDTIME "
161 "DP_VIDEO_SUBTITLES "
165 "DP_SV_BOUNCEFACTOR "
166 "DP_SV_CLIENTCAMERA "
167 "DP_SV_CLIENTCOLORS "
170 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
171 "DP_SV_DISABLECLIENTPREDICTION "
172 "DP_SV_DISCARDABLEDEMO "
173 "DP_SV_DRAWONLYTOCLIENT "
176 "DP_SV_ENTITYCONTENTSTRANSITION "
177 "DP_SV_MODELFLAGS_AS_EFFECTS "
178 "DP_SV_MOVETYPESTEP_LANDEVENT "
180 "DP_SV_NODRAWTOCLIENT "
181 "DP_SV_ONENTITYNOSPAWNFUNCTION "
182 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
184 "DP_SV_PING_PACKETLOSS "
185 "DP_SV_PLAYERPHYSICS "
187 "DP_SV_POINTPARTICLES "
189 "DP_SV_PRECACHEANYTIME "
193 "DP_SV_ROTATINGBMODEL "
197 "DP_SV_SPAWNFUNC_PREFIX "
198 "DP_SV_WRITEPICTURE "
199 "DP_SV_WRITEUNTERMINATEDSTRING "
203 "DP_TE_EXPLOSIONRGB "
205 "DP_TE_PARTICLECUBE "
206 "DP_TE_PARTICLERAIN "
207 "DP_TE_PARTICLESNOW "
209 "DP_TE_QUADEFFECTS1 "
212 "DP_TE_STANDARDEFFECTBUILTINS "
213 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
218 "FTE_CSQC_SKELETONOBJECTS "
221 "KRIMZON_SV_PARSECLIENTCOMMAND "
224 "NEXUIZ_PLAYERMODEL "
226 "PRYDON_CLIENTCURSOR "
227 "TENEBRAE_GFX_DLIGHTS "
230 //"EXT_CSQC " // not ready yet
237 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.
239 setorigin (entity, origin)
242 static void VM_SV_setorigin(prvm_prog_t *prog)
246 VM_SAFEPARMCOUNT(2, VM_setorigin);
248 e = PRVM_G_EDICT(OFS_PARM0);
249 if (e == prog->edicts)
251 VM_Warning(prog, "setorigin: can not modify world entity\n");
254 if (e->priv.server->free)
256 VM_Warning(prog, "setorigin: can not modify free entity\n");
259 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), PRVM_serveredictvector(e, origin));
260 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
261 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
265 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
266 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qboolean rotate)
270 for (i=0 ; i<3 ; i++)
272 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
274 // set derived values
275 VectorCopy (min, PRVM_serveredictvector(e, mins));
276 VectorCopy (max, PRVM_serveredictvector(e, maxs));
277 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
286 the size box is rotated by the current angle
287 LordHavoc: no it isn't...
289 setsize (entity, minvector, maxvector)
292 static void VM_SV_setsize(prvm_prog_t *prog)
297 VM_SAFEPARMCOUNT(3, VM_setsize);
299 e = PRVM_G_EDICT(OFS_PARM0);
300 if (e == prog->edicts)
302 VM_Warning(prog, "setsize: can not modify world entity\n");
305 if (e->priv.server->free)
307 VM_Warning(prog, "setsize: can not modify free entity\n");
310 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), mins);
311 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), maxs);
312 SetMinMaxSize(prog, e, mins, maxs, false);
320 setmodel(entity, model)
323 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
324 static void VM_SV_setmodel(prvm_prog_t *prog)
330 VM_SAFEPARMCOUNT(2, VM_setmodel);
332 e = PRVM_G_EDICT(OFS_PARM0);
333 if (e == prog->edicts)
335 VM_Warning(prog, "setmodel: can not modify world entity\n");
338 if (e->priv.server->free)
340 VM_Warning(prog, "setmodel: can not modify free entity\n");
343 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
344 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
345 PRVM_serveredictfloat(e, modelindex) = i;
347 mod = SV_GetModelByIndex(i);
351 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
352 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
354 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
357 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
364 single print to a specific client
366 sprint(clientent, value)
369 static void VM_SV_sprint(prvm_prog_t *prog)
373 char string[VM_STRINGTEMP_LENGTH];
375 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
377 VM_VarString(prog, 1, string, sizeof(string));
379 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
380 // LordHavoc: div0 requested that sprintto world operate like print
387 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
389 VM_Warning(prog, "tried to centerprint to a non-client\n");
393 client = svs.clients + entnum-1;
394 if (!client->netconnection)
397 MSG_WriteChar(&client->netconnection->message,svc_print);
398 MSG_WriteString(&client->netconnection->message, string);
406 single print to a specific client
408 centerprint(clientent, value)
411 static void VM_SV_centerprint(prvm_prog_t *prog)
415 char string[VM_STRINGTEMP_LENGTH];
417 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
419 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
421 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
423 VM_Warning(prog, "tried to centerprint to a non-client\n");
427 client = svs.clients + entnum-1;
428 if (!client->netconnection)
431 VM_VarString(prog, 1, string, sizeof(string));
432 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
433 MSG_WriteString(&client->netconnection->message, string);
440 particle(origin, color, count)
443 static void VM_SV_particle(prvm_prog_t *prog)
449 VM_SAFEPARMCOUNT(4, VM_SV_particle);
451 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
452 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
453 color = (int)PRVM_G_FLOAT(OFS_PARM2);
454 count = (int)PRVM_G_FLOAT(OFS_PARM3);
455 SV_StartParticle (org, dir, color, count);
465 static void VM_SV_ambientsound(prvm_prog_t *prog)
469 prvm_vec_t vol, attenuation;
472 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
474 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
475 samp = PRVM_G_STRING(OFS_PARM1);
476 vol = PRVM_G_FLOAT(OFS_PARM2);
477 attenuation = PRVM_G_FLOAT(OFS_PARM3);
479 // check to see if samp was properly precached
480 soundnum = SV_SoundIndex(samp, 1);
488 // add an svc_spawnambient command to the level signon packet
491 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
493 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
495 MSG_WriteVector(&sv.signon, pos, sv.protocol);
497 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
498 MSG_WriteShort (&sv.signon, soundnum);
500 MSG_WriteByte (&sv.signon, soundnum);
502 MSG_WriteByte (&sv.signon, (int)(vol*255));
503 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
511 Each entity can have eight independant sound sources, like voice,
514 Channel 0 is an auto-allocate channel, the others override anything
515 already running on that entity/channel pair.
517 An attenuation of 0 will play full volume everywhere in the level.
518 Larger attenuations will drop off.
522 static void VM_SV_sound(prvm_prog_t *prog)
526 prvm_edict_t *entity;
532 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
534 entity = PRVM_G_EDICT(OFS_PARM0);
535 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
536 sample = PRVM_G_STRING(OFS_PARM2);
537 nvolume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
540 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
544 attenuation = PRVM_G_FLOAT(OFS_PARM4);
548 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
553 if(channel >= 8 && channel <= 15) // weird QW feature
555 flags |= CHANNELFLAG_RELIABLE;
561 // LordHavoc: we only let the qc set certain flags, others are off-limits
562 flags = (int)PRVM_G_FLOAT(OFS_PARM6) & (CHANNELFLAG_RELIABLE | CHANNELFLAG_FORCELOOP | CHANNELFLAG_PAUSED | CHANNELFLAG_FULLVOLUME);
565 if (nvolume < 0 || nvolume > 255)
567 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
571 if (attenuation < 0 || attenuation > 4)
573 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
577 channel = CHAN_USER2ENGINE(channel);
579 if (!IS_CHAN(channel))
581 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
585 SV_StartSound (entity, channel, sample, nvolume, attenuation, flags & CHANNELFLAG_RELIABLE, pitchchange);
592 Follows the same logic as VM_SV_sound, except instead of
593 an entity, an origin for the sound is provided, and channel
594 is omitted (since no entity is being tracked).
598 static void VM_SV_pointsound(prvm_prog_t *prog)
606 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
608 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
609 sample = PRVM_G_STRING(OFS_PARM1);
610 nvolume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
611 attenuation = PRVM_G_FLOAT(OFS_PARM3);
612 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
614 if (nvolume < 0 || nvolume > 255)
616 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
620 if (attenuation < 0 || attenuation > 4)
622 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
626 SV_StartPointSound (org, sample, nvolume, attenuation, pitchchange);
633 Used for use tracing and shot targeting
634 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
635 if the tryents flag is set.
637 traceline (vector1, vector2, movetype, ignore)
640 static void VM_SV_traceline(prvm_prog_t *prog)
647 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
649 prog->xfunction->builtinsprofile += 30;
651 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
652 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), v2);
653 move = (int)PRVM_G_FLOAT(OFS_PARM2);
654 ent = PRVM_G_EDICT(OFS_PARM3);
656 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]))
657 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));
659 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtracelinelength.value);
661 VM_SetTraceGlobals(prog, &trace);
669 Used for use tracing and shot targeting
670 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
671 if the tryents flag is set.
673 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
676 // LordHavoc: added this for my own use, VERY useful, similar to traceline
677 static void VM_SV_tracebox(prvm_prog_t *prog)
679 vec3_t v1, v2, m1, m2;
684 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
686 prog->xfunction->builtinsprofile += 30;
688 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
689 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), m1);
690 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), m2);
691 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), v2);
692 move = (int)PRVM_G_FLOAT(OFS_PARM4);
693 ent = PRVM_G_EDICT(OFS_PARM5);
695 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]))
696 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));
698 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtraceboxlength.value);
700 VM_SetTraceGlobals(prog, &trace);
703 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
707 vec3_t move, end, tossentorigin, tossentmins, tossentmaxs;
708 vec3_t original_origin;
709 vec3_t original_velocity;
710 vec3_t original_angles;
711 vec3_t original_avelocity;
714 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
715 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
716 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
717 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
719 gravity = PRVM_serveredictfloat(tossent, gravity);
722 gravity *= sv_gravity.value * 0.025;
724 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
726 SV_CheckVelocity (tossent);
727 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
728 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
729 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
730 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
731 VectorCopy(PRVM_serveredictvector(tossent, origin), tossentorigin);
732 VectorCopy(PRVM_serveredictvector(tossent, mins), tossentmins);
733 VectorCopy(PRVM_serveredictvector(tossent, maxs), tossentmaxs);
734 trace = SV_TraceBox(tossentorigin, tossentmins, tossentmaxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent), 0, 0, collision_extendmovelength.value);
735 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
736 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
738 if (trace.fraction < 1)
742 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
743 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
744 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
745 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
750 static void VM_SV_tracetoss(prvm_prog_t *prog)
754 prvm_edict_t *ignore;
756 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
758 prog->xfunction->builtinsprofile += 600;
760 ent = PRVM_G_EDICT(OFS_PARM0);
761 if (ent == prog->edicts)
763 VM_Warning(prog, "tracetoss: can not use world entity\n");
766 ignore = PRVM_G_EDICT(OFS_PARM1);
768 trace = SV_Trace_Toss(prog, ent, ignore);
770 VM_SetTraceGlobals(prog, &trace);
773 //============================================================================
775 static int checkpvsbytes;
776 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
778 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
784 // cycle to the next one
786 check = bound(1, check, svs.maxclients);
787 if (check == svs.maxclients)
795 prog->xfunction->builtinsprofile++;
797 if (i == svs.maxclients+1)
799 // look up the client's edict
800 ent = PRVM_EDICT_NUM(i);
801 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
802 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
804 // found a valid client (possibly the same one again)
808 // get the PVS for the entity
809 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
811 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
812 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
821 Returns a client (or object that has a client enemy) that would be a
824 If there is more than one valid option, they are cycled each frame
826 If (self.origin + self.viewofs) is not in the PVS of the current target,
827 it is not returned at all.
832 int c_invis, c_notvis;
833 static void VM_SV_checkclient(prvm_prog_t *prog)
835 prvm_edict_t *ent, *self;
838 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
840 // find a new check if on a new frame
841 if (sv.time - sv.lastchecktime >= 0.1)
843 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
844 sv.lastchecktime = sv.time;
847 // return check if it might be visible
848 ent = PRVM_EDICT_NUM(sv.lastcheck);
849 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
851 VM_RETURN_EDICT(prog->edicts);
855 // if current entity can't possibly see the check entity, return 0
856 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
857 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
858 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
861 VM_RETURN_EDICT(prog->edicts);
865 // might be able to see it
867 VM_RETURN_EDICT(ent);
870 //============================================================================
876 Checks if an entity is in a point's PVS.
877 Should be fast but can be inexact.
879 float checkpvs(vector viewpos, entity viewee) = #240;
882 static void VM_SV_checkpvs(prvm_prog_t *prog)
884 vec3_t viewpos, absmin, absmax;
885 prvm_edict_t *viewee;
890 unsigned char fatpvs[MAX_MAP_LEAFS/8];
893 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
894 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
895 viewee = PRVM_G_EDICT(OFS_PARM1);
897 if(viewee->priv.server->free)
899 VM_Warning(prog, "checkpvs: can not check free entity\n");
900 PRVM_G_FLOAT(OFS_RETURN) = 4;
905 if(!sv.worldmodel || !sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
907 // no PVS support on this worldmodel... darn
908 PRVM_G_FLOAT(OFS_RETURN) = 3;
911 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
914 // viewpos isn't in any PVS... darn
915 PRVM_G_FLOAT(OFS_RETURN) = 2;
918 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
919 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
920 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, absmin, absmax);
922 // using fat PVS like FTEQW does (slow)
923 if(!sv.worldmodel || !sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
925 // no PVS support on this worldmodel... darn
926 PRVM_G_FLOAT(OFS_RETURN) = 3;
929 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
932 // viewpos isn't in any PVS... darn
933 PRVM_G_FLOAT(OFS_RETURN) = 2;
936 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
937 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
938 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, absmin, absmax);
947 Sends text over to the client's execution buffer
949 stuffcmd (clientent, value, ...)
952 static void VM_SV_stuffcmd(prvm_prog_t *prog)
956 char string[VM_STRINGTEMP_LENGTH];
958 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
960 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
961 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
963 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
967 VM_VarString(prog, 1, string, sizeof(string));
970 host_client = svs.clients + entnum-1;
971 Host_ClientCommands ("%s", string);
979 Returns a chain of entities that have origins within a spherical area
981 findradius (origin, radius)
984 static void VM_SV_findradius(prvm_prog_t *prog)
986 prvm_edict_t *ent, *chain;
987 vec_t radius, radius2;
988 vec3_t org, eorg, mins, maxs;
991 static prvm_edict_t *touchedicts[MAX_EDICTS];
994 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
997 chainfield = PRVM_G_INT(OFS_PARM2);
999 chainfield = prog->fieldoffsets.chain;
1001 prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
1003 chain = (prvm_edict_t *)prog->edicts;
1005 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1006 radius = PRVM_G_FLOAT(OFS_PARM1);
1007 radius2 = radius * radius;
1009 mins[0] = org[0] - (radius + 1);
1010 mins[1] = org[1] - (radius + 1);
1011 mins[2] = org[2] - (radius + 1);
1012 maxs[0] = org[0] + (radius + 1);
1013 maxs[1] = org[1] + (radius + 1);
1014 maxs[2] = org[2] + (radius + 1);
1015 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1016 if (numtouchedicts > MAX_EDICTS)
1018 // this never happens
1019 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1020 numtouchedicts = MAX_EDICTS;
1022 for (i = 0;i < numtouchedicts;i++)
1024 ent = touchedicts[i];
1025 prog->xfunction->builtinsprofile++;
1026 // Quake did not return non-solid entities but darkplaces does
1027 // (note: this is the reason you can't blow up fallen zombies)
1028 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1030 // LordHavoc: compare against bounding box rather than center so it
1031 // doesn't miss large objects, and use DotProduct instead of Length
1032 // for a major speedup
1033 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1034 if (sv_gameplayfix_findradiusdistancetobox.integer)
1036 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1037 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1038 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1041 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1042 if (DotProduct(eorg, eorg) < radius2)
1044 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1049 VM_RETURN_EDICT(chain);
1052 static void VM_SV_precache_sound(prvm_prog_t *prog)
1054 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1055 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1058 static void VM_SV_precache_model(prvm_prog_t *prog)
1060 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1061 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1062 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1069 float(float yaw, float dist[, settrace]) walkmove
1072 static void VM_SV_walkmove(prvm_prog_t *prog)
1081 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1083 // assume failure if it returns early
1084 PRVM_G_FLOAT(OFS_RETURN) = 0;
1086 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1087 if (ent == prog->edicts)
1089 VM_Warning(prog, "walkmove: can not modify world entity\n");
1092 if (ent->priv.server->free)
1094 VM_Warning(prog, "walkmove: can not modify free entity\n");
1097 yaw = PRVM_G_FLOAT(OFS_PARM0);
1098 dist = PRVM_G_FLOAT(OFS_PARM1);
1099 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1101 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1104 yaw = yaw*M_PI*2 / 360;
1106 move[0] = cos(yaw)*dist;
1107 move[1] = sin(yaw)*dist;
1110 // save program state, because SV_movestep may call other progs
1111 oldf = prog->xfunction;
1112 oldself = PRVM_serverglobaledict(self);
1114 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1117 // restore program state
1118 prog->xfunction = oldf;
1119 PRVM_serverglobaledict(self) = oldself;
1130 static void VM_SV_droptofloor(prvm_prog_t *prog)
1133 vec3_t end, entorigin, entmins, entmaxs;
1136 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1138 // assume failure if it returns early
1139 PRVM_G_FLOAT(OFS_RETURN) = 0;
1141 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1142 if (ent == prog->edicts)
1144 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1147 if (ent->priv.server->free)
1149 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1153 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1156 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1157 SV_NudgeOutOfSolid(ent);
1159 VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
1160 VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
1161 VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
1162 trace = SV_TraceBox(entorigin, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
1163 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1166 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]);
1167 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1168 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
1169 VectorSubtract(trace.endpos, offset, trace.endpos);
1170 if (trace.startsolid)
1172 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]);
1174 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1175 PRVM_serveredictedict(ent, groundentity) = 0;
1176 PRVM_G_FLOAT(OFS_RETURN) = 1;
1178 else if (trace.fraction < 1)
1180 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]);
1181 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1182 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1183 SV_NudgeOutOfSolid(ent);
1185 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1186 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1187 PRVM_G_FLOAT(OFS_RETURN) = 1;
1188 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1189 ent->priv.server->suspendedinairflag = true;
1194 if (!trace.allsolid && trace.fraction < 1)
1196 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1198 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1199 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1200 PRVM_G_FLOAT(OFS_RETURN) = 1;
1201 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1202 ent->priv.server->suspendedinairflag = true;
1211 void(float style, string value) lightstyle
1214 static void VM_SV_lightstyle(prvm_prog_t *prog)
1221 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1223 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1224 val = PRVM_G_STRING(OFS_PARM1);
1226 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1227 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1230 // change the string in sv
1231 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1233 // send message to all clients on this server
1234 if (sv.state != ss_active)
1237 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1239 if (client->active && client->netconnection)
1241 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1242 MSG_WriteChar (&client->netconnection->message,style);
1243 MSG_WriteString (&client->netconnection->message, val);
1253 static void VM_SV_checkbottom(prvm_prog_t *prog)
1255 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1256 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1264 static void VM_SV_pointcontents(prvm_prog_t *prog)
1267 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1268 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point);
1269 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(SV_PointSuperContents(point));
1276 Pick a vector for the player to shoot along
1277 vector aim(entity, missilespeed)
1280 static void VM_SV_aim(prvm_prog_t *prog)
1282 prvm_edict_t *ent, *check, *bestent;
1283 vec3_t start, dir, end, bestdir;
1286 float dist, bestdist;
1289 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1291 // assume failure if it returns early
1292 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1293 // if sv_aim is so high it can't possibly accept anything, skip out early
1294 if (sv_aim.value >= 1)
1297 ent = PRVM_G_EDICT(OFS_PARM0);
1298 if (ent == prog->edicts)
1300 VM_Warning(prog, "aim: can not use world entity\n");
1303 if (ent->priv.server->free)
1305 VM_Warning(prog, "aim: can not use free entity\n");
1308 //speed = PRVM_G_FLOAT(OFS_PARM1);
1310 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1313 // try sending a trace straight
1314 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1315 VectorMA (start, 2048, dir, end);
1316 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1317 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1318 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1320 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1325 // try all possible entities
1326 VectorCopy (dir, bestdir);
1327 bestdist = sv_aim.value;
1330 check = PRVM_NEXT_EDICT(prog->edicts);
1331 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1333 prog->xfunction->builtinsprofile++;
1334 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1338 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1339 continue; // don't aim at teammate
1340 for (j=0 ; j<3 ; j++)
1341 end[j] = PRVM_serveredictvector(check, origin)[j]
1342 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1343 VectorSubtract (end, start, dir);
1344 VectorNormalize (dir);
1345 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1346 if (dist < bestdist)
1347 continue; // to far to turn
1348 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1349 if (tr.ent == check)
1350 { // can shoot at this one
1358 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1359 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1360 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1362 VectorNormalize (end);
1363 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1367 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1372 ===============================================================================
1376 ===============================================================================
1379 #define MSG_BROADCAST 0 // unreliable to all
1380 #define MSG_ONE 1 // reliable to one (msg_entity)
1381 #define MSG_ALL 2 // reliable to all
1382 #define MSG_INIT 3 // write to the init string
1383 #define MSG_ENTITY 5
1385 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1391 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1395 return &sv.datagram;
1398 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1399 entnum = PRVM_NUM_FOR_EDICT(ent);
1400 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1402 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1403 return &sv.reliable_datagram;
1406 return &svs.clients[entnum-1].netconnection->message;
1409 VM_Warning(prog, "WriteDest: bad destination\n");
1411 return &sv.reliable_datagram;
1417 return sv.writeentitiestoclient_msg;
1423 static void VM_SV_WriteByte(prvm_prog_t *prog)
1425 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1426 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1429 static void VM_SV_WriteChar(prvm_prog_t *prog)
1431 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1432 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1435 static void VM_SV_WriteShort(prvm_prog_t *prog)
1437 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1438 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1441 static void VM_SV_WriteLong(prvm_prog_t *prog)
1443 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1444 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1447 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1449 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1450 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1453 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1455 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1456 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1459 static void VM_SV_WriteString(prvm_prog_t *prog)
1461 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1462 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1465 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1467 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1468 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1472 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1474 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1475 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1478 // writes a picture as at most size bytes of data
1480 // IMGNAME \0 SIZE(short) IMGDATA
1481 // if failed to read/compress:
1483 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1484 static void VM_SV_WritePicture(prvm_prog_t *prog)
1486 const char *imgname;
1490 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1492 imgname = PRVM_G_STRING(OFS_PARM1);
1493 size = (size_t) PRVM_G_FLOAT(OFS_PARM2);
1497 MSG_WriteString(WriteDest(prog), imgname);
1498 if(Image_Compress(imgname, size, &buf, &size))
1501 MSG_WriteShort(WriteDest(prog), (int)size);
1502 SZ_Write(WriteDest(prog), (unsigned char *) buf, (int)size);
1507 MSG_WriteShort(WriteDest(prog), 0);
1511 //////////////////////////////////////////////////////////
1513 static void VM_SV_makestatic(prvm_prog_t *prog)
1518 // allow 0 parameters due to an id1 qc bug in which this function is used
1519 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1520 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1522 if (prog->argc >= 1)
1523 ent = PRVM_G_EDICT(OFS_PARM0);
1525 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1526 if (ent == prog->edicts)
1528 VM_Warning(prog, "makestatic: can not modify world entity\n");
1531 if (ent->priv.server->free)
1533 VM_Warning(prog, "makestatic: can not modify free entity\n");
1538 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1543 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1544 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1545 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1547 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1549 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1550 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1551 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1555 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1556 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1557 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1560 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1561 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1562 for (i=0 ; i<3 ; i++)
1564 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1565 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1568 // throw the entity away now
1569 PRVM_ED_Free(prog, ent);
1572 //=============================================================================
1579 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1585 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1587 ent = PRVM_G_EDICT(OFS_PARM0);
1588 i = PRVM_NUM_FOR_EDICT(ent);
1589 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1591 Con_Print("tried to setspawnparms on a non-client\n");
1595 // copy spawn parms out of the client_t
1596 client = svs.clients + i-1;
1597 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1598 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1605 Returns a color vector indicating the lighting at the requested point.
1607 (Internal Operation note: actually measures the light beneath the point, just like
1608 the model lighting on the client)
1613 static void VM_SV_getlight(prvm_prog_t *prog)
1615 vec3_t ambientcolor, diffusecolor, diffusenormal;
1617 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1618 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
1619 VectorClear(ambientcolor);
1620 VectorClear(diffusecolor);
1621 VectorClear(diffusenormal);
1622 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1623 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1624 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1629 unsigned char type; // 1/2/8 or other value if isn't used
1633 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1634 static int vm_customstats_last;
1636 void VM_CustomStats_Clear (void)
1640 Z_Free(vm_customstats);
1641 vm_customstats = NULL;
1642 vm_customstats_last = -1;
1646 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1648 prvm_prog_t *prog = SVVM_prog;
1659 for(i=0; i<vm_customstats_last+1 ;i++)
1661 if(!vm_customstats[i].type)
1663 switch(vm_customstats[i].type)
1665 //string as 16 bytes
1668 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1669 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1670 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1671 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1672 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1674 //float field sent as-is
1676 // can't directly use PRVM_E_INT on the field because it may be PRVM_64 and a double is not the representation we want to send
1677 u.f = PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1680 //integer value of float field
1682 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1690 // void(float index, float type, .void field) SV_AddStat = #232;
1691 // Set up an auto-sent player stat.
1692 // Client's get thier own fields sent to them. Index may not be less than 32.
1693 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1694 // 1: string (4 stats carrying a total of 16 charactures)
1695 // 2: float (one stat, float converted to an integer for transportation)
1696 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1697 static void VM_SV_AddStat(prvm_prog_t *prog)
1702 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1706 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1709 VM_Warning(prog, "PF_SV_AddStat: not enough memory\n");
1713 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1714 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1715 off = PRVM_G_INT (OFS_PARM2);
1720 VM_Warning(prog, "PF_SV_AddStat: index may not be less than 32\n");
1723 if(i >= (MAX_CL_STATS-32))
1725 VM_Warning(prog, "PF_SV_AddStat: index >= MAX_CL_STATS\n");
1728 if(i > (MAX_CL_STATS-32-4) && type == 1)
1730 VM_Warning(prog, "PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1733 vm_customstats[i].type = type;
1734 vm_customstats[i].fieldoffset = off;
1735 if(vm_customstats_last < i)
1736 vm_customstats_last = i;
1743 copies data from one entity to another
1745 copyentity(src, dst)
1748 static void VM_SV_copyentity(prvm_prog_t *prog)
1750 prvm_edict_t *in, *out;
1751 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1752 in = PRVM_G_EDICT(OFS_PARM0);
1753 if (in == prog->edicts)
1755 VM_Warning(prog, "copyentity: can not read world entity\n");
1758 if (in->priv.server->free)
1760 VM_Warning(prog, "copyentity: can not read free entity\n");
1763 out = PRVM_G_EDICT(OFS_PARM1);
1764 if (out == prog->edicts)
1766 VM_Warning(prog, "copyentity: can not modify world entity\n");
1769 if (out->priv.server->free)
1771 VM_Warning(prog, "copyentity: can not modify free entity\n");
1774 memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
1783 sets the color of a client and broadcasts the update to all connected clients
1785 setcolor(clientent, value)
1788 static void VM_SV_setcolor(prvm_prog_t *prog)
1793 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1794 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1795 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1797 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1799 Con_Print("tried to setcolor a non-client\n");
1803 client = svs.clients + entnum-1;
1806 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1807 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1810 if (client->old_colors != client->colors)
1812 client->old_colors = client->colors;
1813 // send notification to all clients
1814 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1815 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1816 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1824 effect(origin, modelname, startframe, framecount, framerate)
1827 static void VM_SV_effect(prvm_prog_t *prog)
1832 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1833 s = PRVM_G_STRING(OFS_PARM1);
1836 VM_Warning(prog, "effect: no model specified\n");
1840 i = SV_ModelIndex(s, 1);
1843 VM_Warning(prog, "effect: model not precached\n");
1847 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1849 VM_Warning(prog, "effect: framecount < 1\n");
1853 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1855 VM_Warning(prog, "effect: framerate < 1\n");
1859 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1860 SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1863 static void VM_SV_te_blood(prvm_prog_t *prog)
1865 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1866 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1868 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1869 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1873 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1875 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1876 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1877 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1879 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1880 SV_FlushBroadcastMessages();
1883 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1885 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1886 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1888 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1889 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1891 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1892 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1893 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1895 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1896 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1901 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1902 SV_FlushBroadcastMessages();
1905 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1907 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1908 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1909 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1911 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1912 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1913 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1915 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1916 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1917 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1918 SV_FlushBroadcastMessages();
1921 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1923 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1924 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1926 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1927 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1934 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1941 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1943 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1944 // gravity true/false
1945 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1948 SV_FlushBroadcastMessages();
1951 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1953 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1954 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1956 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1957 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1964 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1965 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1971 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1973 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1974 SV_FlushBroadcastMessages();
1977 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1979 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1980 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1982 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1983 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1985 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1989 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1990 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1991 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1993 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1994 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1995 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1997 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1999 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2000 SV_FlushBroadcastMessages();
2003 static void VM_SV_te_spark(prvm_prog_t *prog)
2005 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
2006 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2008 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2009 MSG_WriteByte(&sv.datagram, TE_SPARK);
2011 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2012 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2015 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2016 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2017 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2019 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2020 SV_FlushBroadcastMessages();
2023 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2025 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2026 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2027 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2029 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2030 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2031 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2032 SV_FlushBroadcastMessages();
2035 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2037 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2038 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2039 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2041 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2042 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2043 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2044 SV_FlushBroadcastMessages();
2047 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2049 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2050 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2051 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2054 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2055 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2056 SV_FlushBroadcastMessages();
2059 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2061 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2062 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2063 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2065 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2066 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2067 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2068 SV_FlushBroadcastMessages();
2071 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2073 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2074 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2075 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2077 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2078 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2079 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2080 SV_FlushBroadcastMessages();
2083 static void VM_SV_te_customflash(prvm_prog_t *prog)
2085 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2086 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2088 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2089 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2091 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2092 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2093 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2095 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2097 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2099 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2100 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2101 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2102 SV_FlushBroadcastMessages();
2105 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2107 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2108 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2109 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2111 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2112 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2113 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2114 SV_FlushBroadcastMessages();
2117 static void VM_SV_te_spike(prvm_prog_t *prog)
2119 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2120 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2121 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2123 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2124 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2125 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2126 SV_FlushBroadcastMessages();
2129 static void VM_SV_te_superspike(prvm_prog_t *prog)
2131 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2132 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2133 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2135 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2136 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2137 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2138 SV_FlushBroadcastMessages();
2141 static void VM_SV_te_explosion(prvm_prog_t *prog)
2143 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2144 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2145 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2147 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2148 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2149 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2150 SV_FlushBroadcastMessages();
2153 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2155 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2156 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2157 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2159 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2160 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2161 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2162 SV_FlushBroadcastMessages();
2165 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2167 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2168 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2169 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2171 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2172 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2173 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2174 SV_FlushBroadcastMessages();
2177 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2179 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2180 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2181 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2183 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2184 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2185 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2186 SV_FlushBroadcastMessages();
2189 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2191 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2192 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2193 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2195 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2196 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2197 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2198 SV_FlushBroadcastMessages();
2201 static void VM_SV_te_teleport(prvm_prog_t *prog)
2203 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2204 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2205 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2207 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2208 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2209 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2210 SV_FlushBroadcastMessages();
2213 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2215 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2216 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2217 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2219 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2220 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2221 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2223 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2224 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2225 SV_FlushBroadcastMessages();
2228 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2230 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2231 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2232 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2234 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2236 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2237 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2238 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2240 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2241 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2242 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2243 SV_FlushBroadcastMessages();
2246 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2248 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2249 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2250 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2252 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2254 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2255 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2256 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2258 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2259 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2260 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2261 SV_FlushBroadcastMessages();
2264 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2266 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2267 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2268 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2270 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2272 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2273 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2274 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2276 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2277 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2278 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2279 SV_FlushBroadcastMessages();
2282 static void VM_SV_te_beam(prvm_prog_t *prog)
2284 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2285 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2286 MSG_WriteByte(&sv.datagram, TE_BEAM);
2288 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2290 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2291 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2292 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2294 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2295 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2296 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2297 SV_FlushBroadcastMessages();
2300 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2302 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2303 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2304 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2305 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2306 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2307 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2308 SV_FlushBroadcastMessages();
2311 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2313 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2314 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2315 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2317 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2318 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2319 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2321 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2322 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2323 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2325 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2326 SV_FlushBroadcastMessages();
2329 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2330 //this function originally written by KrimZon, made shorter by LordHavoc
2331 static void VM_SV_clientcommand(prvm_prog_t *prog)
2333 client_t *temp_client;
2335 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2337 //find client for this entity
2338 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2339 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2341 Con_Print("PF_clientcommand: entity is not a client\n");
2345 temp_client = host_client;
2346 host_client = svs.clients + i;
2347 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
2348 host_client = temp_client;
2351 //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)
2352 static void VM_SV_setattachment(prvm_prog_t *prog)
2354 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2355 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2356 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2359 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2361 if (e == prog->edicts)
2363 VM_Warning(prog, "setattachment: can not modify world entity\n");
2366 if (e->priv.server->free)
2368 VM_Warning(prog, "setattachment: can not modify free entity\n");
2372 if (tagentity == NULL)
2373 tagentity = prog->edicts;
2377 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2379 model = SV_GetModelFromEdict(tagentity);
2382 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2384 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);
2387 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));
2390 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2391 PRVM_serveredictfloat(e, tag_index) = tagindex;
2394 /////////////////////////////////////////
2395 // DP_MD3_TAGINFO extension coded by VorteX
2397 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2401 i = (int)PRVM_serveredictfloat(e, modelindex);
2402 if (i < 1 || i >= MAX_MODELS)
2405 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2408 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2415 Matrix4x4_CreateIdentity(tag_localmatrix);
2417 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2419 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2430 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2433 float pitchsign = 1;
2435 scale = PRVM_serveredictfloat(ent, scale);
2440 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);
2443 pitchsign = SV_GetPitchSign(prog, ent);
2444 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);
2448 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2451 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2453 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2454 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2455 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2456 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2458 *out = identitymatrix;
2462 // Warnings/errors code:
2463 // 0 - normal (everything all-right)
2466 // 3 - null or non-precached model
2467 // 4 - no tags with requested index
2468 // 5 - runaway loop at attachment chain
2469 extern cvar_t cl_bob;
2470 extern cvar_t cl_bobcycle;
2471 extern cvar_t cl_bobup;
2472 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2475 int modelindex, attachloop;
2476 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2479 *out = identitymatrix; // warnings and errors return identical matrix
2481 if (ent == prog->edicts)
2483 if (ent->priv.server->free)
2486 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2487 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2490 model = SV_GetModelByIndex(modelindex);
2492 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2493 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2494 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2496 tagmatrix = identitymatrix;
2497 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2501 if (attachloop >= 256) // prevent runaway looping
2503 // apply transformation by child's tagindex on parent entity and then
2504 // by parent entity itself
2505 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2506 if (ret && attachloop == 0)
2508 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2509 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2510 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2511 // next iteration we process the parent entity
2512 if (PRVM_serveredictedict(ent, tag_entity))
2514 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2515 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2522 // RENDER_VIEWMODEL magic
2523 if (PRVM_serveredictedict(ent, viewmodelforclient))
2525 Matrix4x4_Copy(&tagmatrix, out);
2526 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2528 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2529 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2532 // Cl_bob, ported from rendering code
2533 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2536 // LordHavoc: this code is *weird*, but not replacable (I think it
2537 // should be done in QC on the server, but oh well, quake is quake)
2538 // LordHavoc: figured out bobup: the time at which the sin is at 180
2539 // degrees (which allows lengthening or squishing the peak or valley)
2540 cycle = sv.time/cl_bobcycle.value;
2541 cycle -= (int)cycle;
2542 if (cycle < cl_bobup.value)
2543 cycle = sin(M_PI * cycle / cl_bobup.value);
2545 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2546 // bob is proportional to velocity in the xy plane
2547 // (don't count Z, or jumping messes it up)
2548 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;
2549 bob = bob*0.3 + bob*0.7*cycle;
2550 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2557 //float(entity ent, string tagname) gettagindex;
2559 static void VM_SV_gettagindex(prvm_prog_t *prog)
2562 const char *tag_name;
2565 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2567 ent = PRVM_G_EDICT(OFS_PARM0);
2568 tag_name = PRVM_G_STRING(OFS_PARM1);
2570 if (ent == prog->edicts)
2572 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2575 if (ent->priv.server->free)
2577 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2582 if (!SV_GetModelFromEdict(ent))
2583 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2586 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2588 if(developer_extra.integer)
2589 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2591 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2594 //vector(entity ent, float tagindex) gettaginfo;
2595 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2599 matrix4x4_t tag_matrix;
2600 matrix4x4_t tag_localmatrix;
2602 const char *tagname;
2604 vec3_t forward, left, up, origin;
2605 const dp_model_t *model;
2607 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2609 e = PRVM_G_EDICT(OFS_PARM0);
2610 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2612 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2613 Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
2614 VectorCopy(forward, PRVM_serverglobalvector(v_forward));
2615 VectorNegate(left, PRVM_serverglobalvector(v_right));
2616 VectorCopy(up, PRVM_serverglobalvector(v_up));
2617 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2618 model = SV_GetModelFromEdict(e);
2619 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2620 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2621 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2622 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2623 Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
2625 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2626 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2627 VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
2628 VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
2629 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2630 VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset));
2635 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2638 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2641 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2644 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2647 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2652 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2653 static void VM_SV_dropclient(prvm_prog_t *prog)
2656 client_t *oldhostclient;
2657 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2658 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2659 if (clientnum < 0 || clientnum >= svs.maxclients)
2661 VM_Warning(prog, "dropclient: not a client\n");
2664 if (!svs.clients[clientnum].active)
2666 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2669 oldhostclient = host_client;
2670 host_client = svs.clients + clientnum;
2671 SV_DropClient(false);
2672 host_client = oldhostclient;
2675 //entity() spawnclient (DP_SV_BOTCLIENT)
2676 static void VM_SV_spawnclient(prvm_prog_t *prog)
2680 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2681 prog->xfunction->builtinsprofile += 2;
2683 for (i = 0;i < svs.maxclients;i++)
2685 if (!svs.clients[i].active)
2687 prog->xfunction->builtinsprofile += 100;
2688 SV_ConnectClient (i, NULL);
2689 // this has to be set or else ClientDisconnect won't be called
2690 // we assume the qc will call ClientConnect...
2691 svs.clients[i].clientconnectcalled = true;
2692 ed = PRVM_EDICT_NUM(i + 1);
2696 VM_RETURN_EDICT(ed);
2699 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2700 static void VM_SV_clienttype(prvm_prog_t *prog)
2703 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2704 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2705 if (clientnum < 0 || clientnum >= svs.maxclients)
2706 PRVM_G_FLOAT(OFS_RETURN) = 3;
2707 else if (!svs.clients[clientnum].active)
2708 PRVM_G_FLOAT(OFS_RETURN) = 0;
2709 else if (svs.clients[clientnum].netconnection)
2710 PRVM_G_FLOAT(OFS_RETURN) = 1;
2712 PRVM_G_FLOAT(OFS_RETURN) = 2;
2719 string(string key) serverkey
2722 static void VM_SV_serverkey(prvm_prog_t *prog)
2724 char string[VM_STRINGTEMP_LENGTH];
2725 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2726 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2727 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2730 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2731 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2736 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2738 e = PRVM_G_EDICT(OFS_PARM0);
2739 if (e == prog->edicts)
2741 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2744 if (e->priv.server->free)
2746 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2749 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2750 if (i <= 0 || i >= MAX_MODELS)
2752 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2755 if (!sv.model_precache[i][0])
2757 VM_Warning(prog, "setmodelindex: model not precached\n");
2761 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2762 PRVM_serveredictfloat(e, modelindex) = i;
2764 mod = SV_GetModelByIndex(i);
2768 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2769 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2771 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2774 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2777 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2778 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2781 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2783 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2785 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2786 if (i <= 0 || i >= MAX_MODELS)
2788 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2791 if (!sv.model_precache[i][0])
2793 VM_Warning(prog, "modelnameforindex: model not precached\n");
2797 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2800 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2801 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2804 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2805 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2808 PRVM_G_FLOAT(OFS_RETURN) = i;
2811 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2812 static void VM_SV_trailparticles(prvm_prog_t *prog)
2815 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2817 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2820 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2821 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2822 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2823 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start);
2824 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end);
2825 MSG_WriteVector(&sv.datagram, start, sv.protocol);
2826 MSG_WriteVector(&sv.datagram, end, sv.protocol);
2827 SV_FlushBroadcastMessages();
2830 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2831 static void VM_SV_pointparticles(prvm_prog_t *prog)
2833 int effectnum, count;
2835 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2837 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2840 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2841 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2842 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2843 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2844 if (count == 1 && !VectorLength2(vel))
2847 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2848 MSG_WriteShort(&sv.datagram, effectnum);
2849 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2853 // 1+2+12+12+2=29 bytes
2854 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2855 MSG_WriteShort(&sv.datagram, effectnum);
2856 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2857 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2858 MSG_WriteShort(&sv.datagram, count);
2861 SV_FlushBroadcastMessages();
2864 //PF_setpause, // void(float pause) setpause = #531;
2865 static void VM_SV_setpause(prvm_prog_t *prog) {
2867 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2868 if (pauseValue != 0) { //pause the game
2870 sv.pausedstart = realtime;
2871 } else { //disable pause, in case it was enabled
2872 if (sv.paused != 0) {
2877 // send notification to all clients
2878 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2879 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2882 // #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.
2883 static void VM_SV_skel_create(prvm_prog_t *prog)
2885 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2886 dp_model_t *model = SV_GetModelByIndex(modelindex);
2887 skeleton_t *skeleton;
2889 PRVM_G_FLOAT(OFS_RETURN) = 0;
2890 if (!model || !model->num_bones)
2892 for (i = 0;i < MAX_EDICTS;i++)
2893 if (!prog->skeletons[i])
2895 if (i == MAX_EDICTS)
2897 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(prog->progs_mempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2898 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2899 skeleton->model = model;
2900 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2901 // initialize to identity matrices
2902 for (i = 0;i < skeleton->model->num_bones;i++)
2903 skeleton->relativetransforms[i] = identitymatrix;
2906 // #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
2907 static void VM_SV_skel_build(prvm_prog_t *prog)
2909 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2910 skeleton_t *skeleton;
2911 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2912 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2913 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2914 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2915 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2916 dp_model_t *model = SV_GetModelByIndex(modelindex);
2920 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2921 frameblend_t frameblend[MAX_FRAMEBLENDS];
2922 matrix4x4_t bonematrix;
2924 PRVM_G_FLOAT(OFS_RETURN) = 0;
2925 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2927 firstbone = max(0, firstbone);
2928 lastbone = min(lastbone, model->num_bones - 1);
2929 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2930 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2931 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time);
2932 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2934 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2936 memset(&bonematrix, 0, sizeof(bonematrix));
2937 for (blendindex = 0;blendindex < numblends;blendindex++)
2939 Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2940 Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp);
2942 Matrix4x4_Normalize3(&bonematrix, &bonematrix);
2943 Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac);
2945 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2948 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2949 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
2951 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2952 skeleton_t *skeleton;
2953 PRVM_G_FLOAT(OFS_RETURN) = 0;
2954 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2956 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2959 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2960 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
2962 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2963 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2964 skeleton_t *skeleton;
2965 PRVM_G_INT(OFS_RETURN) = 0;
2966 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2968 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2970 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
2973 // #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)
2974 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
2976 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2977 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2978 skeleton_t *skeleton;
2979 PRVM_G_FLOAT(OFS_RETURN) = 0;
2980 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2982 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2984 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2987 // #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
2988 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
2990 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2991 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2992 skeleton_t *skeleton;
2993 PRVM_G_FLOAT(OFS_RETURN) = 0;
2994 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2996 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2999 // #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)
3000 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
3002 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3003 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3004 skeleton_t *skeleton;
3006 vec3_t forward, left, up, origin;
3007 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3008 VectorClear(PRVM_clientglobalvector(v_forward));
3009 VectorClear(PRVM_clientglobalvector(v_right));
3010 VectorClear(PRVM_clientglobalvector(v_up));
3011 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3013 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3015 matrix = skeleton->relativetransforms[bonenum];
3016 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3017 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3018 VectorNegate(left, PRVM_clientglobalvector(v_right));
3019 VectorCopy(up, PRVM_clientglobalvector(v_up));
3020 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3023 // #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)
3024 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
3026 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3027 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3028 skeleton_t *skeleton;
3031 vec3_t forward, left, up, origin;
3032 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3033 VectorClear(PRVM_clientglobalvector(v_forward));
3034 VectorClear(PRVM_clientglobalvector(v_right));
3035 VectorClear(PRVM_clientglobalvector(v_up));
3036 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3038 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3040 matrix = skeleton->relativetransforms[bonenum];
3041 // convert to absolute
3042 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3045 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3047 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3048 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3049 VectorNegate(left, PRVM_clientglobalvector(v_right));
3050 VectorCopy(up, PRVM_clientglobalvector(v_up));
3051 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3054 // #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)
3055 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3057 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3058 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3059 vec3_t forward, left, up, origin;
3060 skeleton_t *skeleton;
3062 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3064 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3066 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3067 VectorNegate(PRVM_clientglobalvector(v_right), left);
3068 VectorCopy(PRVM_clientglobalvector(v_up), up);
3069 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3070 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3071 skeleton->relativetransforms[bonenum] = matrix;
3074 // #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)
3075 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3077 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3078 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3079 vec3_t forward, left, up, origin;
3080 skeleton_t *skeleton;
3083 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3085 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3087 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3088 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3089 VectorNegate(PRVM_clientglobalvector(v_right), left);
3090 VectorCopy(PRVM_clientglobalvector(v_up), up);
3091 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3092 temp = skeleton->relativetransforms[bonenum];
3093 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3096 // #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)
3097 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3099 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3100 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3101 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3103 vec3_t forward, left, up, origin;
3104 skeleton_t *skeleton;
3107 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3109 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3110 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3111 VectorNegate(PRVM_clientglobalvector(v_right), left);
3112 VectorCopy(PRVM_clientglobalvector(v_up), up);
3113 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3114 firstbone = max(0, firstbone);
3115 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3116 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3118 temp = skeleton->relativetransforms[bonenum];
3119 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3123 // #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
3124 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3126 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3127 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3128 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3129 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3131 skeleton_t *skeletondst;
3132 skeleton_t *skeletonsrc;
3133 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3135 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3137 firstbone = max(0, firstbone);
3138 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3139 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3140 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3141 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3144 // #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)
3145 static void VM_SV_skel_delete(prvm_prog_t *prog)
3147 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3148 skeleton_t *skeleton;
3149 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3152 prog->skeletons[skeletonindex] = NULL;
3155 // #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
3156 static void VM_SV_frameforname(prvm_prog_t *prog)
3158 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3159 dp_model_t *model = SV_GetModelByIndex(modelindex);
3160 const char *name = PRVM_G_STRING(OFS_PARM1);
3162 PRVM_G_FLOAT(OFS_RETURN) = -1;
3163 if (!model || !model->animscenes)
3165 for (i = 0;i < model->numframes;i++)
3167 if (!strcasecmp(model->animscenes[i].name, name))
3169 PRVM_G_FLOAT(OFS_RETURN) = i;
3175 // #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.
3176 static void VM_SV_frameduration(prvm_prog_t *prog)
3178 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3179 dp_model_t *model = SV_GetModelByIndex(modelindex);
3180 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3181 PRVM_G_FLOAT(OFS_RETURN) = 0;
3182 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3184 if (model->animscenes[framenum].framerate)
3185 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3189 prvm_builtin_t vm_sv_builtins[] = {
3190 NULL, // #0 NULL function (not callable) (QUAKE)
3191 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3192 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3193 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3194 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3195 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3196 VM_break, // #6 void() break (QUAKE)
3197 VM_random, // #7 float() random (QUAKE)
3198 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3199 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3200 VM_error, // #10 void(string e) error (QUAKE)
3201 VM_objerror, // #11 void(string e) objerror (QUAKE)
3202 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3203 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3204 VM_spawn, // #14 entity() spawn (QUAKE)
3205 VM_remove, // #15 void(entity e) remove (QUAKE)
3206 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3207 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3208 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3209 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3210 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3211 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3212 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3213 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3214 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3215 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3216 VM_ftos, // #26 string(float f) ftos (QUAKE)
3217 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3218 VM_coredump, // #28 void() coredump (QUAKE)
3219 VM_traceon, // #29 void() traceon (QUAKE)
3220 VM_traceoff, // #30 void() traceoff (QUAKE)
3221 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3222 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3223 NULL, // #33 (QUAKE)
3224 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3225 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3226 VM_rint, // #36 float(float v) rint (QUAKE)
3227 VM_floor, // #37 float(float v) floor (QUAKE)
3228 VM_ceil, // #38 float(float v) ceil (QUAKE)
3229 NULL, // #39 (QUAKE)
3230 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3231 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3232 NULL, // #42 (QUAKE)
3233 VM_fabs, // #43 float(float f) fabs (QUAKE)
3234 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3235 VM_cvar, // #45 float(string s) cvar (QUAKE)
3236 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3237 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3238 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3239 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3240 NULL, // #50 (QUAKE)
3241 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3242 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3243 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3244 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3245 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3246 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3247 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3248 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3249 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3250 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3251 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3252 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3253 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3254 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3255 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3256 NULL, // #66 (QUAKE)
3257 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3258 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3259 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3260 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3261 NULL, // #71 (QUAKE)
3262 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3263 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3264 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3265 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3266 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3267 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3268 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3269 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3270 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3271 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3272 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3273 NULL, // #83 (QUAKE)
3274 NULL, // #84 (QUAKE)
3275 NULL, // #85 (QUAKE)
3276 NULL, // #86 (QUAKE)
3277 NULL, // #87 (QUAKE)
3278 NULL, // #88 (QUAKE)
3279 NULL, // #89 (QUAKE)
3280 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3281 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3282 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3283 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3284 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3285 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3286 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3287 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3288 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3289 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3290 // FrikaC and Telejano range #100-#199
3301 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3302 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3303 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3304 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3305 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3306 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3307 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3308 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3309 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3310 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3391 // FTEQW range #200-#299
3410 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3413 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3414 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3415 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3416 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3417 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3418 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3419 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3420 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3421 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3422 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3424 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3432 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3455 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.
3456 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
3457 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3458 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3459 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)
3460 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
3461 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)
3462 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)
3463 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)
3464 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)
3465 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)
3466 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
3467 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)
3468 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
3469 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.
3492 // CSQC range #300-#399
3493 NULL, // #300 void() clearscene (EXT_CSQC)
3494 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3495 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3496 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3497 NULL, // #304 void() renderscene (EXT_CSQC)
3498 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3499 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3500 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3501 NULL, // #308 void() R_EndPolygon
3503 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3504 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3508 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3509 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3510 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3511 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3512 NULL, // #319 void(string name) freepic (EXT_CSQC)
3513 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3514 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3515 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3516 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3517 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3518 NULL, // #325 void(void) drawresetcliparea
3523 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3524 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3525 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3526 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3527 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3528 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3529 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3530 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3531 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3532 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3533 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3534 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3535 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3536 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3537 NULL, // #344 vector() getmousepos (EXT_CSQC)
3538 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3539 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3540 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3541 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3542 NULL, // #349 float() isdemo (EXT_CSQC)
3543 VM_isserver, // #350 float() isserver (EXT_CSQC)
3544 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3545 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3546 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3547 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3553 NULL, // #360 float() readbyte (EXT_CSQC)
3554 NULL, // #361 float() readchar (EXT_CSQC)
3555 NULL, // #362 float() readshort (EXT_CSQC)
3556 NULL, // #363 float() readlong (EXT_CSQC)
3557 NULL, // #364 float() readcoord (EXT_CSQC)
3558 NULL, // #365 float() readangle (EXT_CSQC)
3559 NULL, // #366 string() readstring (EXT_CSQC)
3560 NULL, // #367 float() readfloat (EXT_CSQC)
3593 // LordHavoc's range #400-#499
3594 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3595 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3596 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3597 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3598 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3599 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3600 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3601 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3602 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)
3603 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3604 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3605 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3606 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3607 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3608 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3609 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3610 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3611 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3612 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3613 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3614 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3615 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3616 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3617 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3618 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3619 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3620 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3621 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3622 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3623 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3624 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3625 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3626 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3627 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3628 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3629 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3630 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3631 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3632 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3633 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3634 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3635 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3636 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3637 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3638 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3639 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3640 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3641 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3642 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3643 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3644 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3645 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3646 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3647 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3648 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3649 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3650 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3651 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3653 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3654 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3655 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3656 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3657 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3658 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3659 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3660 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3661 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3662 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3663 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3665 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3666 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3667 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3668 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3669 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3670 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3671 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3672 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3673 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3674 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3675 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3676 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3677 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3678 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3679 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3680 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3688 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3689 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3690 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3691 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3692 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3693 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3694 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3695 VM_SV_WritePicture, // #501
3697 VM_whichpack, // #503 string(string) whichpack = #503;
3704 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3705 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3706 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3707 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)
3708 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3709 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3710 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3711 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3712 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3713 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3723 VM_loadfromdata, // #529
3724 VM_loadfromfile, // #530
3725 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3727 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3728 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3729 VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP)
3730 VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP)
3731 VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP)
3732 VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP)
3734 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3735 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3736 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3799 VM_callfunction, // #605
3800 VM_writetofile, // #606
3801 VM_isfunction, // #607
3807 VM_parseentitydata, // #613
3818 VM_SV_getextresponse, // #624 string getextresponse(void)
3821 VM_sprintf, // #627 string sprintf(string format, ...)
3822 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3823 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3833 VM_digest_hex, // #639
3836 VM_coverage, // #642
3840 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3842 void SVVM_init_cmd(prvm_prog_t *prog)
3847 void SVVM_reset_cmd(prvm_prog_t *prog)
3849 World_End(&sv.world);
3851 if(prog->loaded && PRVM_serverfunction(SV_Shutdown))
3853 func_t s = PRVM_serverfunction(SV_Shutdown);
3854 PRVM_serverglobalfloat(time) = sv.time;
3855 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3856 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");