6 //============================================================================
11 char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
22 "DP_CSQC_ENTITYNOCULL "
23 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
24 "DP_CSQC_MULTIFRAME_INTERPOLATION "
25 "DP_CSQC_SPAWNPARTICLE "
37 "DP_EF_RESTARTANIM_BIT "
42 "DP_ENT_CUSTOMCOLORMAP "
43 "DP_ENT_EXTERIORMODELTOCLIENT "
46 "DP_ENT_LOWPRECISION "
50 "DP_GFX_EXTERNALTEXTURES "
51 "DP_GFX_EXTERNALTEXTURES_PERMAP "
53 "DP_GFX_MODEL_INTERPOLATION "
54 "DP_GFX_QUAKE3MODELTAGS "
58 "DP_HALFLIFE_MAP_CVAR "
61 "DP_LIGHTSTYLE_STATICVALUE "
65 "DP_MOVETYPEBOUNCEMISSILE "
68 "DP_QC_ASINACOSATANATAN2TAN "
74 "DP_QC_CVAR_DEFSTRING "
75 "DP_QC_CVAR_DESCRIPTION "
82 "DP_QC_EXTRESPONSEPACKET "
84 "DP_QC_FINDCHAINFLAGS "
85 "DP_QC_FINDCHAINFLOAT "
86 "DP_QC_FINDCHAIN_TOFIELD "
92 "DP_QC_GETSURFACETRIANGLE "
93 "DP_QC_GETSURFACEPOINTATTRIBUTE "
95 "DP_QC_GETTAGINFO_BONEPROPERTIES "
97 "DP_QC_GETTIME_CDTRACK "
100 "DP_QC_MULTIPLETEMPSTRINGS "
101 "DP_QC_NUM_FOR_EDICT "
103 "DP_QC_SINCOSSQRTPOW "
106 "DP_QC_STRINGBUFFERS "
107 "DP_QC_STRINGBUFFERS_CVARLIST "
108 "DP_QC_STRINGCOLORFUNCTIONS "
109 "DP_QC_STRING_CASE_FUNCTIONS "
111 "DP_QC_TOKENIZEBYSEPARATOR "
112 "DP_QC_TOKENIZE_CONSOLE "
115 "DP_QC_TRACE_MOVETYPE_HITMODEL "
116 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
117 "DP_QC_UNLIMITEDTEMPSTRINGS "
120 "DP_QC_VECTOANGLES_WITH_ROLL "
121 "DP_QC_VECTORVECTORS "
128 "DP_SKELETONOBJECTS "
129 "DP_SND_DIRECTIONLESSATTNNONE "
137 "DP_SV_BOUNCEFACTOR "
138 "DP_SV_CLIENTCOLORS "
141 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
142 "DP_SV_DRAWONLYTOCLIENT "
145 "DP_SV_ENTITYCONTENTSTRANSITION "
146 "DP_SV_MODELFLAGS_AS_EFFECTS "
147 "DP_SV_MOVETYPESTEP_LANDEVENT "
149 "DP_SV_NODRAWTOCLIENT "
150 "DP_SV_ONENTITYNOSPAWNFUNCTION "
151 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
153 "DP_SV_PING_PACKETLOSS "
154 "DP_SV_PLAYERPHYSICS "
155 "DP_SV_POINTPARTICLES "
157 "DP_SV_PRECACHEANYTIME "
161 "DP_SV_ROTATINGBMODEL "
165 "DP_SV_SPAWNFUNC_PREFIX "
166 "DP_SV_WRITEPICTURE "
167 "DP_SV_WRITEUNTERMINATEDSTRING "
171 "DP_TE_EXPLOSIONRGB "
173 "DP_TE_PARTICLECUBE "
174 "DP_TE_PARTICLERAIN "
175 "DP_TE_PARTICLESNOW "
177 "DP_TE_QUADEFFECTS1 "
180 "DP_TE_STANDARDEFFECTBUILTINS "
181 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
185 "FTE_CSQC_SKELETONOBJECTS "
188 "KRIMZON_SV_PARSECLIENTCOMMAND "
191 "NEXUIZ_PLAYERMODEL "
193 "PRYDON_CLIENTCURSOR "
194 "TENEBRAE_GFX_DLIGHTS "
197 //"EXT_CSQC " // not ready yet
204 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.
206 setorigin (entity, origin)
209 static void VM_SV_setorigin (void)
214 VM_SAFEPARMCOUNT(2, VM_setorigin);
216 e = PRVM_G_EDICT(OFS_PARM0);
217 if (e == prog->edicts)
219 VM_Warning("setorigin: can not modify world entity\n");
222 if (e->priv.server->free)
224 VM_Warning("setorigin: can not modify free entity\n");
227 org = PRVM_G_VECTOR(OFS_PARM1);
228 VectorCopy (org, e->fields.server->origin);
232 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
233 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
237 for (i=0 ; i<3 ; i++)
239 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
241 // set derived values
242 VectorCopy (min, e->fields.server->mins);
243 VectorCopy (max, e->fields.server->maxs);
244 VectorSubtract (max, min, e->fields.server->size);
253 the size box is rotated by the current angle
254 LordHavoc: no it isn't...
256 setsize (entity, minvector, maxvector)
259 static void VM_SV_setsize (void)
264 VM_SAFEPARMCOUNT(3, VM_setsize);
266 e = PRVM_G_EDICT(OFS_PARM0);
267 if (e == prog->edicts)
269 VM_Warning("setsize: can not modify world entity\n");
272 if (e->priv.server->free)
274 VM_Warning("setsize: can not modify free entity\n");
277 min = PRVM_G_VECTOR(OFS_PARM1);
278 max = PRVM_G_VECTOR(OFS_PARM2);
279 SetMinMaxSize (e, min, max, false);
287 setmodel(entity, model)
290 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
291 static void VM_SV_setmodel (void)
297 VM_SAFEPARMCOUNT(2, VM_setmodel);
299 e = PRVM_G_EDICT(OFS_PARM0);
300 if (e == prog->edicts)
302 VM_Warning("setmodel: can not modify world entity\n");
305 if (e->priv.server->free)
307 VM_Warning("setmodel: can not modify free entity\n");
310 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
311 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
312 e->fields.server->modelindex = i;
314 mod = SV_GetModelByIndex(i);
318 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
319 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
321 SetMinMaxSize (e, quakemins, quakemaxs, true);
324 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
331 single print to a specific client
333 sprint(clientent, value)
336 static void VM_SV_sprint (void)
340 char string[VM_STRINGTEMP_LENGTH];
342 VM_VarString(1, string, sizeof(string));
344 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
346 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
347 // LordHavoc: div0 requested that sprintto world operate like print
354 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
356 VM_Warning("tried to centerprint to a non-client\n");
360 client = svs.clients + entnum-1;
361 if (!client->netconnection)
364 MSG_WriteChar(&client->netconnection->message,svc_print);
365 MSG_WriteString(&client->netconnection->message, string);
373 single print to a specific client
375 centerprint(clientent, value)
378 static void VM_SV_centerprint (void)
382 char string[VM_STRINGTEMP_LENGTH];
384 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
386 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
388 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
390 VM_Warning("tried to centerprint to a non-client\n");
394 client = svs.clients + entnum-1;
395 if (!client->netconnection)
398 VM_VarString(1, string, sizeof(string));
399 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
400 MSG_WriteString(&client->netconnection->message, string);
407 particle(origin, color, count)
410 static void VM_SV_particle (void)
416 VM_SAFEPARMCOUNT(4, VM_SV_particle);
418 org = PRVM_G_VECTOR(OFS_PARM0);
419 dir = PRVM_G_VECTOR(OFS_PARM1);
420 color = PRVM_G_FLOAT(OFS_PARM2);
421 count = PRVM_G_FLOAT(OFS_PARM3);
422 SV_StartParticle (org, dir, (int)color, (int)count);
432 static void VM_SV_ambientsound (void)
436 float vol, attenuation;
439 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
441 pos = PRVM_G_VECTOR (OFS_PARM0);
442 samp = PRVM_G_STRING(OFS_PARM1);
443 vol = PRVM_G_FLOAT(OFS_PARM2);
444 attenuation = PRVM_G_FLOAT(OFS_PARM3);
446 // check to see if samp was properly precached
447 soundnum = SV_SoundIndex(samp, 1);
455 // add an svc_spawnambient command to the level signon packet
458 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
460 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
462 MSG_WriteVector(&sv.signon, pos, sv.protocol);
464 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
465 MSG_WriteShort (&sv.signon, soundnum);
467 MSG_WriteByte (&sv.signon, soundnum);
469 MSG_WriteByte (&sv.signon, (int)(vol*255));
470 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
478 Each entity can have eight independant sound sources, like voice,
481 Channel 0 is an auto-allocate channel, the others override anything
482 already running on that entity/channel pair.
484 An attenuation of 0 will play full volume everywhere in the level.
485 Larger attenuations will drop off.
489 static void VM_SV_sound (void)
493 prvm_edict_t *entity;
497 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
499 entity = PRVM_G_EDICT(OFS_PARM0);
500 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
501 sample = PRVM_G_STRING(OFS_PARM2);
502 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
503 attenuation = PRVM_G_FLOAT(OFS_PARM4);
506 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
510 if (volume < 0 || volume > 255)
512 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
516 if (attenuation < 0 || attenuation > 4)
518 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
522 if (channel < 0 || channel > 7)
524 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
528 SV_StartSound (entity, channel, sample, volume, attenuation);
535 Follows the same logic as VM_SV_sound, except instead of
536 an entity, an origin for the sound is provided, and channel
537 is omitted (since no entity is being tracked).
541 static void VM_SV_pointsound(void)
548 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
550 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
551 sample = PRVM_G_STRING(OFS_PARM1);
552 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
553 attenuation = PRVM_G_FLOAT(OFS_PARM3);
555 if (volume < 0 || volume > 255)
557 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
561 if (attenuation < 0 || attenuation > 4)
563 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
567 SV_StartPointSound (org, sample, volume, attenuation);
574 Used for use tracing and shot targeting
575 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
576 if the tryents flag is set.
578 traceline (vector1, vector2, movetype, ignore)
581 static void VM_SV_traceline (void)
588 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
590 prog->xfunction->builtinsprofile += 30;
592 v1 = PRVM_G_VECTOR(OFS_PARM0);
593 v2 = PRVM_G_VECTOR(OFS_PARM1);
594 move = (int)PRVM_G_FLOAT(OFS_PARM2);
595 ent = PRVM_G_EDICT(OFS_PARM3);
597 if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
598 PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
600 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
602 VM_SetTraceGlobals(&trace);
610 Used for use tracing and shot targeting
611 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
612 if the tryents flag is set.
614 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
617 // LordHavoc: added this for my own use, VERY useful, similar to traceline
618 static void VM_SV_tracebox (void)
620 float *v1, *v2, *m1, *m2;
625 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
627 prog->xfunction->builtinsprofile += 30;
629 v1 = PRVM_G_VECTOR(OFS_PARM0);
630 m1 = PRVM_G_VECTOR(OFS_PARM1);
631 m2 = PRVM_G_VECTOR(OFS_PARM2);
632 v2 = PRVM_G_VECTOR(OFS_PARM3);
633 move = (int)PRVM_G_FLOAT(OFS_PARM4);
634 ent = PRVM_G_EDICT(OFS_PARM5);
636 if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
637 PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_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));
639 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
641 VM_SetTraceGlobals(&trace);
644 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
649 vec3_t original_origin;
650 vec3_t original_velocity;
651 vec3_t original_angles;
652 vec3_t original_avelocity;
656 VectorCopy(tossent->fields.server->origin , original_origin );
657 VectorCopy(tossent->fields.server->velocity , original_velocity );
658 VectorCopy(tossent->fields.server->angles , original_angles );
659 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
661 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
662 if (val != NULL && val->_float != 0)
663 gravity = val->_float;
666 gravity *= sv_gravity.value * 0.025;
668 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
670 SV_CheckVelocity (tossent);
671 tossent->fields.server->velocity[2] -= gravity;
672 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
673 VectorScale (tossent->fields.server->velocity, 0.05, move);
674 VectorAdd (tossent->fields.server->origin, move, end);
675 trace = SV_TraceBox(tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
676 VectorCopy (trace.endpos, tossent->fields.server->origin);
677 tossent->fields.server->velocity[2] -= gravity;
679 if (trace.fraction < 1)
683 VectorCopy(original_origin , tossent->fields.server->origin );
684 VectorCopy(original_velocity , tossent->fields.server->velocity );
685 VectorCopy(original_angles , tossent->fields.server->angles );
686 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
691 static void VM_SV_tracetoss (void)
695 prvm_edict_t *ignore;
697 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
699 prog->xfunction->builtinsprofile += 600;
701 ent = PRVM_G_EDICT(OFS_PARM0);
702 if (ent == prog->edicts)
704 VM_Warning("tracetoss: can not use world entity\n");
707 ignore = PRVM_G_EDICT(OFS_PARM1);
709 trace = SV_Trace_Toss (ent, ignore);
711 VM_SetTraceGlobals(&trace);
714 //============================================================================
716 static int checkpvsbytes;
717 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
719 static int VM_SV_newcheckclient (int check)
725 // cycle to the next one
727 check = bound(1, check, svs.maxclients);
728 if (check == svs.maxclients)
736 prog->xfunction->builtinsprofile++;
738 if (i == svs.maxclients+1)
740 // look up the client's edict
741 ent = PRVM_EDICT_NUM(i);
742 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
743 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
745 // found a valid client (possibly the same one again)
749 // get the PVS for the entity
750 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
752 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
753 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
762 Returns a client (or object that has a client enemy) that would be a
765 If there is more than one valid option, they are cycled each frame
767 If (self.origin + self.viewofs) is not in the PVS of the current target,
768 it is not returned at all.
773 int c_invis, c_notvis;
774 static void VM_SV_checkclient (void)
776 prvm_edict_t *ent, *self;
779 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
781 // find a new check if on a new frame
782 if (sv.time - sv.lastchecktime >= 0.1)
784 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
785 sv.lastchecktime = sv.time;
788 // return check if it might be visible
789 ent = PRVM_EDICT_NUM(sv.lastcheck);
790 if (ent->priv.server->free || ent->fields.server->health <= 0)
792 VM_RETURN_EDICT(prog->edicts);
796 // if current entity can't possibly see the check entity, return 0
797 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
798 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
799 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
802 VM_RETURN_EDICT(prog->edicts);
806 // might be able to see it
808 VM_RETURN_EDICT(ent);
811 //============================================================================
817 Checks if an entity is in a point's PVS.
818 Should be fast but can be inexact.
820 float checkpvs(vector viewpos, entity viewee) = #240;
823 static void VM_SV_checkpvs (void)
826 prvm_edict_t *viewee;
831 unsigned char fatpvs[MAX_MAP_LEAFS/8];
834 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
835 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
836 viewee = PRVM_G_EDICT(OFS_PARM1);
838 if(viewee->priv.server->free)
840 VM_Warning("checkpvs: can not check free entity\n");
841 PRVM_G_FLOAT(OFS_RETURN) = 4;
846 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
848 // no PVS support on this worldmodel... darn
849 PRVM_G_FLOAT(OFS_RETURN) = 3;
852 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
855 // viewpos isn't in any PVS... darn
856 PRVM_G_FLOAT(OFS_RETURN) = 2;
859 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
861 // using fat PVS like FTEQW does (slow)
862 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
864 // no PVS support on this worldmodel... darn
865 PRVM_G_FLOAT(OFS_RETURN) = 3;
868 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
871 // viewpos isn't in any PVS... darn
872 PRVM_G_FLOAT(OFS_RETURN) = 2;
875 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
884 Sends text over to the client's execution buffer
886 stuffcmd (clientent, value, ...)
889 static void VM_SV_stuffcmd (void)
893 char string[VM_STRINGTEMP_LENGTH];
895 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
897 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
898 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
900 VM_Warning("Can't stuffcmd to a non-client\n");
904 VM_VarString(1, string, sizeof(string));
907 host_client = svs.clients + entnum-1;
908 Host_ClientCommands ("%s", string);
916 Returns a chain of entities that have origins within a spherical area
918 findradius (origin, radius)
921 static void VM_SV_findradius (void)
923 prvm_edict_t *ent, *chain;
924 vec_t radius, radius2;
925 vec3_t org, eorg, mins, maxs;
928 static prvm_edict_t *touchedicts[MAX_EDICTS];
931 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
934 chainfield = PRVM_G_INT(OFS_PARM2);
936 chainfield = prog->fieldoffsets.chain;
938 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
940 chain = (prvm_edict_t *)prog->edicts;
942 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
943 radius = PRVM_G_FLOAT(OFS_PARM1);
944 radius2 = radius * radius;
946 mins[0] = org[0] - (radius + 1);
947 mins[1] = org[1] - (radius + 1);
948 mins[2] = org[2] - (radius + 1);
949 maxs[0] = org[0] + (radius + 1);
950 maxs[1] = org[1] + (radius + 1);
951 maxs[2] = org[2] + (radius + 1);
952 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
953 if (numtouchedicts > MAX_EDICTS)
955 // this never happens
956 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
957 numtouchedicts = MAX_EDICTS;
959 for (i = 0;i < numtouchedicts;i++)
961 ent = touchedicts[i];
962 prog->xfunction->builtinsprofile++;
963 // Quake did not return non-solid entities but darkplaces does
964 // (note: this is the reason you can't blow up fallen zombies)
965 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
967 // LordHavoc: compare against bounding box rather than center so it
968 // doesn't miss large objects, and use DotProduct instead of Length
969 // for a major speedup
970 VectorSubtract(org, ent->fields.server->origin, eorg);
971 if (sv_gameplayfix_findradiusdistancetobox.integer)
973 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
974 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
975 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
978 VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
979 if (DotProduct(eorg, eorg) < radius2)
981 PRVM_EDICTFIELDVALUE(ent,chainfield)->edict = PRVM_EDICT_TO_PROG(chain);
986 VM_RETURN_EDICT(chain);
989 static void VM_SV_precache_sound (void)
991 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
992 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
995 static void VM_SV_precache_model (void)
997 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
998 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
999 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1006 float(float yaw, float dist[, settrace]) walkmove
1009 static void VM_SV_walkmove (void)
1018 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1020 // assume failure if it returns early
1021 PRVM_G_FLOAT(OFS_RETURN) = 0;
1023 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1024 if (ent == prog->edicts)
1026 VM_Warning("walkmove: can not modify world entity\n");
1029 if (ent->priv.server->free)
1031 VM_Warning("walkmove: can not modify free entity\n");
1034 yaw = PRVM_G_FLOAT(OFS_PARM0);
1035 dist = PRVM_G_FLOAT(OFS_PARM1);
1036 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1038 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1041 yaw = yaw*M_PI*2 / 360;
1043 move[0] = cos(yaw)*dist;
1044 move[1] = sin(yaw)*dist;
1047 // save program state, because SV_movestep may call other progs
1048 oldf = prog->xfunction;
1049 oldself = prog->globals.server->self;
1051 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1054 // restore program state
1055 prog->xfunction = oldf;
1056 prog->globals.server->self = oldself;
1066 static void VM_SV_droptofloor (void)
1072 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1074 // assume failure if it returns early
1075 PRVM_G_FLOAT(OFS_RETURN) = 0;
1077 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1078 if (ent == prog->edicts)
1080 VM_Warning("droptofloor: can not modify world entity\n");
1083 if (ent->priv.server->free)
1085 VM_Warning("droptofloor: can not modify free entity\n");
1089 VectorCopy (ent->fields.server->origin, end);
1092 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1093 SV_UnstickEntity(ent);
1095 trace = SV_TraceBox(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1096 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1099 VectorSet(offset, 0.5f * (ent->fields.server->mins[0] + ent->fields.server->maxs[0]), 0.5f * (ent->fields.server->mins[1] + ent->fields.server->maxs[1]), ent->fields.server->mins[2]);
1100 VectorAdd(ent->fields.server->origin, offset, org);
1101 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1102 VectorSubtract(trace.endpos, offset, trace.endpos);
1103 if (trace.startsolid)
1105 Con_DPrintf("droptofloor at %f %f %f - COULD NOT FIX BADLY PLACED ENTITY\n", ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2]);
1106 SV_UnstickEntity(ent);
1108 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1109 ent->fields.server->groundentity = 0;
1110 PRVM_G_FLOAT(OFS_RETURN) = 1;
1112 else if (trace.fraction < 1)
1114 Con_DPrintf("droptofloor at %f %f %f - FIXED BADLY PLACED ENTITY\n", ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2]);
1115 VectorCopy (trace.endpos, ent->fields.server->origin);
1116 SV_UnstickEntity(ent);
1118 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1119 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1120 PRVM_G_FLOAT(OFS_RETURN) = 1;
1121 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1122 ent->priv.server->suspendedinairflag = true;
1127 if (trace.fraction != 1)
1129 if (trace.fraction < 1)
1130 VectorCopy (trace.endpos, ent->fields.server->origin);
1132 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1133 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1134 PRVM_G_FLOAT(OFS_RETURN) = 1;
1135 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1136 ent->priv.server->suspendedinairflag = true;
1145 void(float style, string value) lightstyle
1148 static void VM_SV_lightstyle (void)
1155 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1157 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1158 val = PRVM_G_STRING(OFS_PARM1);
1160 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1161 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1164 // change the string in sv
1165 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1167 // send message to all clients on this server
1168 if (sv.state != ss_active)
1171 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1173 if (client->active && client->netconnection)
1175 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1176 MSG_WriteChar (&client->netconnection->message,style);
1177 MSG_WriteString (&client->netconnection->message, val);
1187 static void VM_SV_checkbottom (void)
1189 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1190 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1198 static void VM_SV_pointcontents (void)
1200 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1201 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1208 Pick a vector for the player to shoot along
1209 vector aim(entity, missilespeed)
1212 static void VM_SV_aim (void)
1214 prvm_edict_t *ent, *check, *bestent;
1215 vec3_t start, dir, end, bestdir;
1218 float dist, bestdist;
1221 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1223 // assume failure if it returns early
1224 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1225 // if sv_aim is so high it can't possibly accept anything, skip out early
1226 if (sv_aim.value >= 1)
1229 ent = PRVM_G_EDICT(OFS_PARM0);
1230 if (ent == prog->edicts)
1232 VM_Warning("aim: can not use world entity\n");
1235 if (ent->priv.server->free)
1237 VM_Warning("aim: can not use free entity\n");
1240 //speed = PRVM_G_FLOAT(OFS_PARM1);
1242 VectorCopy (ent->fields.server->origin, start);
1245 // try sending a trace straight
1246 VectorCopy (prog->globals.server->v_forward, dir);
1247 VectorMA (start, 2048, dir, end);
1248 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1249 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1250 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1252 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1257 // try all possible entities
1258 VectorCopy (dir, bestdir);
1259 bestdist = sv_aim.value;
1262 check = PRVM_NEXT_EDICT(prog->edicts);
1263 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1265 prog->xfunction->builtinsprofile++;
1266 if (check->fields.server->takedamage != DAMAGE_AIM)
1270 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1271 continue; // don't aim at teammate
1272 for (j=0 ; j<3 ; j++)
1273 end[j] = check->fields.server->origin[j]
1274 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1275 VectorSubtract (end, start, dir);
1276 VectorNormalize (dir);
1277 dist = DotProduct (dir, prog->globals.server->v_forward);
1278 if (dist < bestdist)
1279 continue; // to far to turn
1280 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1281 if (tr.ent == check)
1282 { // can shoot at this one
1290 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1291 dist = DotProduct (dir, prog->globals.server->v_forward);
1292 VectorScale (prog->globals.server->v_forward, dist, end);
1294 VectorNormalize (end);
1295 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1299 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1304 ===============================================================================
1308 ===============================================================================
1311 #define MSG_BROADCAST 0 // unreliable to all
1312 #define MSG_ONE 1 // reliable to one (msg_entity)
1313 #define MSG_ALL 2 // reliable to all
1314 #define MSG_INIT 3 // write to the init string
1315 #define MSG_ENTITY 5
1317 sizebuf_t *WriteDest (void)
1323 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1327 return &sv.datagram;
1330 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1331 entnum = PRVM_NUM_FOR_EDICT(ent);
1332 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1334 VM_Warning ("WriteDest: tried to write to non-client\n");
1335 return &sv.reliable_datagram;
1338 return &svs.clients[entnum-1].netconnection->message;
1341 VM_Warning ("WriteDest: bad destination\n");
1343 return &sv.reliable_datagram;
1349 return sv.writeentitiestoclient_msg;
1355 static void VM_SV_WriteByte (void)
1357 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1358 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1361 static void VM_SV_WriteChar (void)
1363 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1364 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1367 static void VM_SV_WriteShort (void)
1369 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1370 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1373 static void VM_SV_WriteLong (void)
1375 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1376 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1379 static void VM_SV_WriteAngle (void)
1381 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1382 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1385 static void VM_SV_WriteCoord (void)
1387 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1388 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1391 static void VM_SV_WriteString (void)
1393 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1394 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1397 static void VM_SV_WriteUnterminatedString (void)
1399 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1400 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1403 static void VM_SV_WriteEntity (void)
1405 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1406 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1409 static void VM_SV_WriteByteINT (void)
1411 VM_SAFEPARMCOUNT(2, VM_SV_WriteByteINT);
1412 MSG_WriteByte (WriteDest(), PRVM_G_INT(OFS_PARM1));
1415 static void VM_SV_WriteCharINT (void)
1417 VM_SAFEPARMCOUNT(2, VM_SV_WriteCharINT);
1418 MSG_WriteChar (WriteDest(), PRVM_G_INT(OFS_PARM1));
1421 static void VM_SV_WriteShortINT (void)
1423 VM_SAFEPARMCOUNT(2, VM_SV_WriteShortINT);
1424 MSG_WriteShort (WriteDest(), PRVM_G_INT(OFS_PARM1));
1427 static void VM_SV_WriteLongINT (void)
1429 VM_SAFEPARMCOUNT(2, VM_SV_WriteLongINT);
1430 MSG_WriteLong (WriteDest(), PRVM_G_INT(OFS_PARM1));
1434 // writes a picture as at most size bytes of data
1436 // IMGNAME \0 SIZE(short) IMGDATA
1437 // if failed to read/compress:
1439 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1440 static void VM_SV_WritePicture (void)
1442 const char *imgname;
1446 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1448 imgname = PRVM_G_STRING(OFS_PARM1);
1449 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1453 MSG_WriteString(WriteDest(), imgname);
1454 if(Image_Compress(imgname, size, &buf, &size))
1457 MSG_WriteShort(WriteDest(), size);
1458 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1463 MSG_WriteShort(WriteDest(), 0);
1467 //////////////////////////////////////////////////////////
1469 static void VM_SV_makestatic (void)
1474 // allow 0 parameters due to an id1 qc bug in which this function is used
1475 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1476 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1478 if (prog->argc >= 1)
1479 ent = PRVM_G_EDICT(OFS_PARM0);
1481 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1482 if (ent == prog->edicts)
1484 VM_Warning("makestatic: can not modify world entity\n");
1487 if (ent->priv.server->free)
1489 VM_Warning("makestatic: can not modify free entity\n");
1494 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1499 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1500 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1501 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1503 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1505 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1506 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1507 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1511 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1512 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1513 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1516 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1517 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1518 for (i=0 ; i<3 ; i++)
1520 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1521 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1524 // throw the entity away now
1528 //=============================================================================
1535 static void VM_SV_setspawnparms (void)
1541 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1543 ent = PRVM_G_EDICT(OFS_PARM0);
1544 i = PRVM_NUM_FOR_EDICT(ent);
1545 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1547 Con_Print("tried to setspawnparms on a non-client\n");
1551 // copy spawn parms out of the client_t
1552 client = svs.clients + i-1;
1553 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1554 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1561 Returns a color vector indicating the lighting at the requested point.
1563 (Internal Operation note: actually measures the light beneath the point, just like
1564 the model lighting on the client)
1569 static void VM_SV_getlight (void)
1571 vec3_t ambientcolor, diffusecolor, diffusenormal;
1573 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1574 p = PRVM_G_VECTOR(OFS_PARM0);
1575 VectorClear(ambientcolor);
1576 VectorClear(diffusecolor);
1577 VectorClear(diffusenormal);
1578 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1579 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1580 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1585 unsigned char type; // 1/2/8 or other value if isn't used
1589 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1590 static int vm_customstats_last;
1592 void VM_CustomStats_Clear (void)
1596 Z_Free(vm_customstats);
1597 vm_customstats = NULL;
1598 vm_customstats_last = -1;
1602 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1610 for(i=0; i<vm_customstats_last+1 ;i++)
1612 if(!vm_customstats[i].type)
1614 switch(vm_customstats[i].type)
1616 //string as 16 bytes
1619 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1620 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1621 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1622 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1623 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1625 //float field sent as-is
1627 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1629 //integer value of float field
1631 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1639 // void(float index, float type, .void field) SV_AddStat = #232;
1640 // Set up an auto-sent player stat.
1641 // Client's get thier own fields sent to them. Index may not be less than 32.
1642 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1643 // 1: string (4 stats carrying a total of 16 charactures)
1644 // 2: float (one stat, float converted to an integer for transportation)
1645 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1646 static void VM_SV_AddStat (void)
1651 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1655 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1658 VM_Warning("PF_SV_AddStat: not enough memory\n");
1662 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1663 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1664 off = PRVM_G_INT (OFS_PARM2);
1669 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1672 if(i >= (MAX_CL_STATS-32))
1674 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1677 if(i > (MAX_CL_STATS-32-4) && type == 1)
1679 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1682 vm_customstats[i].type = type;
1683 vm_customstats[i].fieldoffset = off;
1684 if(vm_customstats_last < i)
1685 vm_customstats_last = i;
1692 copies data from one entity to another
1694 copyentity(src, dst)
1697 static void VM_SV_copyentity (void)
1699 prvm_edict_t *in, *out;
1700 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1701 in = PRVM_G_EDICT(OFS_PARM0);
1702 if (in == prog->edicts)
1704 VM_Warning("copyentity: can not read world entity\n");
1707 if (in->priv.server->free)
1709 VM_Warning("copyentity: can not read free entity\n");
1712 out = PRVM_G_EDICT(OFS_PARM1);
1713 if (out == prog->edicts)
1715 VM_Warning("copyentity: can not modify world entity\n");
1718 if (out->priv.server->free)
1720 VM_Warning("copyentity: can not modify free entity\n");
1723 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1732 sets the color of a client and broadcasts the update to all connected clients
1734 setcolor(clientent, value)
1737 static void VM_SV_setcolor (void)
1743 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1744 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1745 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1747 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1749 Con_Print("tried to setcolor a non-client\n");
1753 client = svs.clients + entnum-1;
1756 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1758 client->edict->fields.server->team = (i & 15) + 1;
1761 if (client->old_colors != client->colors)
1763 client->old_colors = client->colors;
1764 // send notification to all clients
1765 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1766 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1767 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1775 effect(origin, modelname, startframe, framecount, framerate)
1778 static void VM_SV_effect (void)
1782 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1783 s = PRVM_G_STRING(OFS_PARM1);
1786 VM_Warning("effect: no model specified\n");
1790 i = SV_ModelIndex(s, 1);
1793 VM_Warning("effect: model not precached\n");
1797 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1799 VM_Warning("effect: framecount < 1\n");
1803 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1805 VM_Warning("effect: framerate < 1\n");
1809 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1812 static void VM_SV_te_blood (void)
1814 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1815 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1817 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1818 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1820 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1821 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1822 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1824 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1825 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1826 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1828 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1829 SV_FlushBroadcastMessages();
1832 static void VM_SV_te_bloodshower (void)
1834 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1835 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1837 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1838 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1840 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1841 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1842 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1844 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1845 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1848 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1850 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1851 SV_FlushBroadcastMessages();
1854 static void VM_SV_te_explosionrgb (void)
1856 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1857 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1858 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1860 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1861 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1862 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1864 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1865 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1866 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1867 SV_FlushBroadcastMessages();
1870 static void VM_SV_te_particlecube (void)
1872 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1873 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1875 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1876 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1878 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1879 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1880 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1882 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1883 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1884 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1886 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1887 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1888 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1890 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1892 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1893 // gravity true/false
1894 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1896 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1897 SV_FlushBroadcastMessages();
1900 static void VM_SV_te_particlerain (void)
1902 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1903 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1905 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1906 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1912 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1913 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1914 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1916 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1917 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1918 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1920 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1922 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1923 SV_FlushBroadcastMessages();
1926 static void VM_SV_te_particlesnow (void)
1928 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1929 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1931 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1932 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1934 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1936 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1942 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1943 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1944 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1946 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1948 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1949 SV_FlushBroadcastMessages();
1952 static void VM_SV_te_spark (void)
1954 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1955 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1957 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1958 MSG_WriteByte(&sv.datagram, TE_SPARK);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1964 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1965 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1966 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1968 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1969 SV_FlushBroadcastMessages();
1972 static void VM_SV_te_gunshotquad (void)
1974 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1975 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1976 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1978 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1979 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1980 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1981 SV_FlushBroadcastMessages();
1984 static void VM_SV_te_spikequad (void)
1986 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1987 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1988 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1990 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1991 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1992 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1993 SV_FlushBroadcastMessages();
1996 static void VM_SV_te_superspikequad (void)
1998 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1999 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2000 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2002 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2004 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2005 SV_FlushBroadcastMessages();
2008 static void VM_SV_te_explosionquad (void)
2010 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2011 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2012 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2014 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2015 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2016 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2017 SV_FlushBroadcastMessages();
2020 static void VM_SV_te_smallflash (void)
2022 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2023 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2024 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2026 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2028 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2029 SV_FlushBroadcastMessages();
2032 static void VM_SV_te_customflash (void)
2034 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2035 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2037 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2038 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2040 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2041 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2042 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2044 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2046 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2048 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2049 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2050 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2051 SV_FlushBroadcastMessages();
2054 static void VM_SV_te_gunshot (void)
2056 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2057 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2058 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2060 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2061 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2062 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2063 SV_FlushBroadcastMessages();
2066 static void VM_SV_te_spike (void)
2068 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2069 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2070 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2072 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2074 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2075 SV_FlushBroadcastMessages();
2078 static void VM_SV_te_superspike (void)
2080 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2081 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2082 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2084 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2085 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2086 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2087 SV_FlushBroadcastMessages();
2090 static void VM_SV_te_explosion (void)
2092 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2093 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2094 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2096 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2097 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2098 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2099 SV_FlushBroadcastMessages();
2102 static void VM_SV_te_tarexplosion (void)
2104 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2105 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2106 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2108 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2109 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2110 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2111 SV_FlushBroadcastMessages();
2114 static void VM_SV_te_wizspike (void)
2116 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2117 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2118 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2120 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2121 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2122 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2123 SV_FlushBroadcastMessages();
2126 static void VM_SV_te_knightspike (void)
2128 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2129 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2130 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2132 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2133 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2134 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2135 SV_FlushBroadcastMessages();
2138 static void VM_SV_te_lavasplash (void)
2140 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2141 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2142 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2144 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2145 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2146 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2147 SV_FlushBroadcastMessages();
2150 static void VM_SV_te_teleport (void)
2152 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2153 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2154 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2156 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2157 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2158 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2159 SV_FlushBroadcastMessages();
2162 static void VM_SV_te_explosion2 (void)
2164 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2165 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2166 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2168 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2169 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2170 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2172 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2173 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2174 SV_FlushBroadcastMessages();
2177 static void VM_SV_te_lightning1 (void)
2179 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2180 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2181 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2183 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2185 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2186 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2187 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2189 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2190 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2191 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2192 SV_FlushBroadcastMessages();
2195 static void VM_SV_te_lightning2 (void)
2197 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2198 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2199 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2201 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2203 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2204 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2205 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2207 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2208 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2209 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2210 SV_FlushBroadcastMessages();
2213 static void VM_SV_te_lightning3 (void)
2215 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2216 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2217 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2219 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2221 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2222 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2223 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2225 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2226 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2227 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2228 SV_FlushBroadcastMessages();
2231 static void VM_SV_te_beam (void)
2233 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2234 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2235 MSG_WriteByte(&sv.datagram, TE_BEAM);
2237 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2239 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2240 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2241 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2243 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2244 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2245 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2246 SV_FlushBroadcastMessages();
2249 static void VM_SV_te_plasmaburn (void)
2251 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2252 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2253 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2254 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2255 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2256 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2257 SV_FlushBroadcastMessages();
2260 static void VM_SV_te_flamejet (void)
2262 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2263 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2264 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2266 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2267 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2268 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2270 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2271 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2272 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2274 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2275 SV_FlushBroadcastMessages();
2278 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2279 //this function originally written by KrimZon, made shorter by LordHavoc
2280 static void VM_SV_clientcommand (void)
2282 client_t *temp_client;
2284 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2286 //find client for this entity
2287 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2288 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2290 Con_Print("PF_clientcommand: entity is not a client\n");
2294 temp_client = host_client;
2295 host_client = svs.clients + i;
2296 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2297 host_client = temp_client;
2300 //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)
2301 static void VM_SV_setattachment (void)
2303 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2304 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2305 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2308 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2310 if (e == prog->edicts)
2312 VM_Warning("setattachment: can not modify world entity\n");
2315 if (e->priv.server->free)
2317 VM_Warning("setattachment: can not modify free entity\n");
2321 if (tagentity == NULL)
2322 tagentity = prog->edicts;
2324 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2326 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2328 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2331 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2333 model = SV_GetModelFromEdict(tagentity);
2336 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2338 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);
2341 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));
2345 /////////////////////////////////////////
2346 // DP_MD3_TAGINFO extension coded by VorteX
2348 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2352 i = (int)e->fields.server->modelindex;
2353 if (i < 1 || i >= MAX_MODELS)
2356 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)e->fields.server->skin, tagname);
2359 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2366 Matrix4x4_CreateIdentity(tag_localmatrix);
2368 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2370 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)e->fields.server->skin, e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2381 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2385 float pitchsign = 1;
2388 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2389 if (val && val->_float != 0)
2390 scale = val->_float;
2393 Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2] + ent->fields.server->view_ofs[2], ent->fields.server->v_angle[0], ent->fields.server->v_angle[1], ent->fields.server->v_angle[2], scale * cl_viewmodel_scale.value);
2396 pitchsign = SV_GetPitchSign(ent);
2397 Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2], pitchsign * ent->fields.server->angles[0], ent->fields.server->angles[1], ent->fields.server->angles[2], scale);
2401 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2404 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2406 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2407 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2408 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2409 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2411 *out = identitymatrix;
2415 // Warnings/errors code:
2416 // 0 - normal (everything all-right)
2419 // 3 - null or non-precached model
2420 // 4 - no tags with requested index
2421 // 5 - runaway loop at attachment chain
2422 extern cvar_t cl_bob;
2423 extern cvar_t cl_bobcycle;
2424 extern cvar_t cl_bobup;
2425 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2429 int modelindex, attachloop;
2430 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2433 *out = identitymatrix; // warnings and errors return identical matrix
2435 if (ent == prog->edicts)
2437 if (ent->priv.server->free)
2440 modelindex = (int)ent->fields.server->modelindex;
2441 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2444 model = SV_GetModelByIndex(modelindex);
2446 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2447 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2448 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2450 tagmatrix = identitymatrix;
2451 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2455 if (attachloop >= 256) // prevent runaway looping
2457 // apply transformation by child's tagindex on parent entity and then
2458 // by parent entity itself
2459 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2460 if (ret && attachloop == 0)
2462 SV_GetEntityMatrix(ent, &entitymatrix, false);
2463 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2464 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2465 // next iteration we process the parent entity
2466 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2468 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2469 ent = PRVM_EDICT_NUM(val->edict);
2476 // RENDER_VIEWMODEL magic
2477 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2479 Matrix4x4_Copy(&tagmatrix, out);
2480 ent = PRVM_EDICT_NUM(val->edict);
2482 SV_GetEntityMatrix(ent, &entitymatrix, true);
2483 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2486 // Cl_bob, ported from rendering code
2487 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2490 // LordHavoc: this code is *weird*, but not replacable (I think it
2491 // should be done in QC on the server, but oh well, quake is quake)
2492 // LordHavoc: figured out bobup: the time at which the sin is at 180
2493 // degrees (which allows lengthening or squishing the peak or valley)
2494 cycle = sv.time/cl_bobcycle.value;
2495 cycle -= (int)cycle;
2496 if (cycle < cl_bobup.value)
2497 cycle = sin(M_PI * cycle / cl_bobup.value);
2499 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2500 // bob is proportional to velocity in the xy plane
2501 // (don't count Z, or jumping messes it up)
2502 bob = sqrt(ent->fields.server->velocity[0]*ent->fields.server->velocity[0] + ent->fields.server->velocity[1]*ent->fields.server->velocity[1])*cl_bob.value;
2503 bob = bob*0.3 + bob*0.7*cycle;
2504 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2511 //float(entity ent, string tagname) gettagindex;
2513 static void VM_SV_gettagindex (void)
2516 const char *tag_name;
2519 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2521 ent = PRVM_G_EDICT(OFS_PARM0);
2522 tag_name = PRVM_G_STRING(OFS_PARM1);
2524 if (ent == prog->edicts)
2526 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2529 if (ent->priv.server->free)
2531 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2536 if (!SV_GetModelFromEdict(ent))
2537 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2540 tag_index = SV_GetTagIndex(ent, tag_name);
2542 if(developer_extra.integer)
2543 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2545 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2548 //vector(entity ent, float tagindex) gettaginfo;
2549 static void VM_SV_gettaginfo (void)
2553 matrix4x4_t tag_matrix;
2554 matrix4x4_t tag_localmatrix;
2556 const char *tagname;
2559 vec3_t fo, le, up, trans;
2560 const dp_model_t *model;
2562 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2564 e = PRVM_G_EDICT(OFS_PARM0);
2565 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2567 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2568 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, le, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2569 VectorScale(le, -1, prog->globals.server->v_right);
2570 model = SV_GetModelFromEdict(e);
2571 VM_GenerateFrameGroupBlend(e->priv.server->framegroupblend, e);
2572 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
2573 VM_UpdateEdictSkeleton(e, model, e->priv.server->frameblend);
2574 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2575 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2577 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_parent)))
2578 val->_float = parentindex;
2579 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_name)))
2580 val->string = tagname ? PRVM_SetTempString(tagname) : 0;
2581 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_offset)))
2582 VectorCopy(trans, val->vector);
2583 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_forward)))
2584 VectorCopy(fo, val->vector);
2585 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_right)))
2586 VectorScale(le, -1, val->vector);
2587 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_up)))
2588 VectorCopy(up, val->vector);
2593 VM_Warning("gettagindex: can't affect world entity\n");
2596 VM_Warning("gettagindex: can't affect free entity\n");
2599 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2602 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2605 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2610 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2611 static void VM_SV_dropclient (void)
2614 client_t *oldhostclient;
2615 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2616 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2617 if (clientnum < 0 || clientnum >= svs.maxclients)
2619 VM_Warning("dropclient: not a client\n");
2622 if (!svs.clients[clientnum].active)
2624 VM_Warning("dropclient: that client slot is not connected\n");
2627 oldhostclient = host_client;
2628 host_client = svs.clients + clientnum;
2629 SV_DropClient(false);
2630 host_client = oldhostclient;
2633 //entity() spawnclient (DP_SV_BOTCLIENT)
2634 static void VM_SV_spawnclient (void)
2638 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2639 prog->xfunction->builtinsprofile += 2;
2641 for (i = 0;i < svs.maxclients;i++)
2643 if (!svs.clients[i].active)
2645 prog->xfunction->builtinsprofile += 100;
2646 SV_ConnectClient (i, NULL);
2647 // this has to be set or else ClientDisconnect won't be called
2648 // we assume the qc will call ClientConnect...
2649 svs.clients[i].clientconnectcalled = true;
2650 ed = PRVM_EDICT_NUM(i + 1);
2654 VM_RETURN_EDICT(ed);
2657 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2658 static void VM_SV_clienttype (void)
2661 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2662 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2663 if (clientnum < 0 || clientnum >= svs.maxclients)
2664 PRVM_G_FLOAT(OFS_RETURN) = 3;
2665 else if (!svs.clients[clientnum].active)
2666 PRVM_G_FLOAT(OFS_RETURN) = 0;
2667 else if (svs.clients[clientnum].netconnection)
2668 PRVM_G_FLOAT(OFS_RETURN) = 1;
2670 PRVM_G_FLOAT(OFS_RETURN) = 2;
2677 string(string key) serverkey
2680 void VM_SV_serverkey(void)
2682 char string[VM_STRINGTEMP_LENGTH];
2683 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2684 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2685 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2688 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2689 static void VM_SV_setmodelindex (void)
2694 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2696 e = PRVM_G_EDICT(OFS_PARM0);
2697 if (e == prog->edicts)
2699 VM_Warning("setmodelindex: can not modify world entity\n");
2702 if (e->priv.server->free)
2704 VM_Warning("setmodelindex: can not modify free entity\n");
2707 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2708 if (i <= 0 || i >= MAX_MODELS)
2710 VM_Warning("setmodelindex: invalid modelindex\n");
2713 if (!sv.model_precache[i][0])
2715 VM_Warning("setmodelindex: model not precached\n");
2719 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2720 e->fields.server->modelindex = i;
2722 mod = SV_GetModelByIndex(i);
2726 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2727 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2729 SetMinMaxSize (e, quakemins, quakemaxs, true);
2732 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2735 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2736 static void VM_SV_modelnameforindex (void)
2739 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2741 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2743 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2744 if (i <= 0 || i >= MAX_MODELS)
2746 VM_Warning("modelnameforindex: invalid modelindex\n");
2749 if (!sv.model_precache[i][0])
2751 VM_Warning("modelnameforindex: model not precached\n");
2755 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2758 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2759 static void VM_SV_particleeffectnum (void)
2762 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2763 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2766 PRVM_G_FLOAT(OFS_RETURN) = i;
2769 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2770 static void VM_SV_trailparticles (void)
2772 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2774 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2777 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2778 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2779 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2780 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2781 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2782 SV_FlushBroadcastMessages();
2785 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2786 static void VM_SV_pointparticles (void)
2788 int effectnum, count;
2790 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2792 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2795 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2796 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2797 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2798 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2799 if (count == 1 && !VectorLength2(vel))
2802 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2803 MSG_WriteShort(&sv.datagram, effectnum);
2804 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2808 // 1+2+12+12+2=29 bytes
2809 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2810 MSG_WriteShort(&sv.datagram, effectnum);
2811 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2812 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2813 MSG_WriteShort(&sv.datagram, count);
2816 SV_FlushBroadcastMessages();
2819 //PF_setpause, // void(float pause) setpause = #531;
2820 static void VM_SV_setpause(void) {
2822 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2823 if (pauseValue != 0) { //pause the game
2825 sv.pausedstart = Sys_DoubleTime();
2826 } else { //disable pause, in case it was enabled
2827 if (sv.paused != 0) {
2832 // send notification to all clients
2833 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2834 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2837 // #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.
2838 static void VM_SV_skel_create(void)
2840 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2841 dp_model_t *model = SV_GetModelByIndex(modelindex);
2842 skeleton_t *skeleton;
2844 PRVM_G_FLOAT(OFS_RETURN) = 0;
2845 if (!model || !model->num_bones)
2847 for (i = 0;i < MAX_EDICTS;i++)
2848 if (!prog->skeletons[i])
2850 if (i == MAX_EDICTS)
2852 prog->skeletons[i] = skeleton = Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2853 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2854 skeleton->model = model;
2855 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2856 // initialize to identity matrices
2857 for (i = 0;i < skeleton->model->num_bones;i++)
2858 skeleton->relativetransforms[i] = identitymatrix;
2861 // #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
2862 static void VM_SV_skel_build(void)
2864 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2865 skeleton_t *skeleton;
2866 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2867 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2868 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2869 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2870 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2871 dp_model_t *model = SV_GetModelByIndex(modelindex);
2876 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2877 frameblend_t frameblend[MAX_FRAMEBLENDS];
2878 matrix4x4_t blendedmatrix;
2880 PRVM_G_FLOAT(OFS_RETURN) = 0;
2881 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2883 firstbone = max(0, firstbone);
2884 lastbone = min(lastbone, model->num_bones - 1);
2885 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2886 VM_GenerateFrameGroupBlend(framegroupblend, ed);
2887 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
2888 blendfrac = 1.0f - retainfrac;
2889 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2890 frameblend[numblends].lerp *= blendfrac;
2891 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2893 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2894 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2895 for (blendindex = 0;blendindex < numblends;blendindex++)
2897 Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2898 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2900 skeleton->relativetransforms[bonenum] = blendedmatrix;
2902 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2905 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2906 static void VM_SV_skel_get_numbones(void)
2908 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2909 skeleton_t *skeleton;
2910 PRVM_G_FLOAT(OFS_RETURN) = 0;
2911 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2913 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2916 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2917 static void VM_SV_skel_get_bonename(void)
2919 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2920 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2921 skeleton_t *skeleton;
2922 PRVM_G_INT(OFS_RETURN) = 0;
2923 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2925 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2927 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(skeleton->model->data_bones[bonenum].name);
2930 // #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)
2931 static void VM_SV_skel_get_boneparent(void)
2933 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2934 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2935 skeleton_t *skeleton;
2936 PRVM_G_FLOAT(OFS_RETURN) = 0;
2937 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2939 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2941 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2944 // #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
2945 static void VM_SV_skel_find_bone(void)
2947 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2948 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2949 skeleton_t *skeleton;
2950 PRVM_G_FLOAT(OFS_RETURN) = 0;
2951 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2953 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2956 // #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)
2957 static void VM_SV_skel_get_bonerel(void)
2959 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2960 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2961 skeleton_t *skeleton;
2963 vec3_t forward, left, up, origin;
2964 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2965 VectorClear(prog->globals.client->v_forward);
2966 VectorClear(prog->globals.client->v_right);
2967 VectorClear(prog->globals.client->v_up);
2968 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2970 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2972 matrix = skeleton->relativetransforms[bonenum];
2973 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2974 VectorCopy(forward, prog->globals.client->v_forward);
2975 VectorNegate(left, prog->globals.client->v_right);
2976 VectorCopy(up, prog->globals.client->v_up);
2977 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2980 // #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)
2981 static void VM_SV_skel_get_boneabs(void)
2983 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2984 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2985 skeleton_t *skeleton;
2988 vec3_t forward, left, up, origin;
2989 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2990 VectorClear(prog->globals.client->v_forward);
2991 VectorClear(prog->globals.client->v_right);
2992 VectorClear(prog->globals.client->v_up);
2993 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2995 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2997 matrix = skeleton->relativetransforms[bonenum];
2998 // convert to absolute
2999 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3002 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3004 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3005 VectorCopy(forward, prog->globals.client->v_forward);
3006 VectorNegate(left, prog->globals.client->v_right);
3007 VectorCopy(up, prog->globals.client->v_up);
3008 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3011 // #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)
3012 static void VM_SV_skel_set_bone(void)
3014 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3015 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3016 vec3_t forward, left, up, origin;
3017 skeleton_t *skeleton;
3019 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3021 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3023 VectorCopy(prog->globals.client->v_forward, forward);
3024 VectorNegate(prog->globals.client->v_right, left);
3025 VectorCopy(prog->globals.client->v_up, up);
3026 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3027 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3028 skeleton->relativetransforms[bonenum] = matrix;
3031 // #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)
3032 static void VM_SV_skel_mul_bone(void)
3034 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3035 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3036 vec3_t forward, left, up, origin;
3037 skeleton_t *skeleton;
3040 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3042 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3044 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3045 VectorCopy(prog->globals.client->v_forward, forward);
3046 VectorNegate(prog->globals.client->v_right, left);
3047 VectorCopy(prog->globals.client->v_up, up);
3048 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3049 temp = skeleton->relativetransforms[bonenum];
3050 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3053 // #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)
3054 static void VM_SV_skel_mul_bones(void)
3056 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3057 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3058 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3060 vec3_t forward, left, up, origin;
3061 skeleton_t *skeleton;
3064 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3066 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3067 VectorCopy(prog->globals.client->v_forward, forward);
3068 VectorNegate(prog->globals.client->v_right, left);
3069 VectorCopy(prog->globals.client->v_up, up);
3070 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3071 firstbone = max(0, firstbone);
3072 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3073 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3075 temp = skeleton->relativetransforms[bonenum];
3076 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3080 // #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
3081 static void VM_SV_skel_copybones(void)
3083 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3084 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3085 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3086 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3088 skeleton_t *skeletondst;
3089 skeleton_t *skeletonsrc;
3090 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3092 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3094 firstbone = max(0, firstbone);
3095 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3096 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3097 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3098 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3101 // #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)
3102 static void VM_SV_skel_delete(void)
3104 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3105 skeleton_t *skeleton;
3106 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3109 prog->skeletons[skeletonindex] = NULL;
3112 // #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
3113 static void VM_SV_frameforname(void)
3115 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3116 dp_model_t *model = SV_GetModelByIndex(modelindex);
3117 const char *name = PRVM_G_STRING(OFS_PARM1);
3119 PRVM_G_FLOAT(OFS_RETURN) = -1;
3120 if (!model || !model->animscenes)
3122 for (i = 0;i < model->numframes;i++)
3124 if (!strcasecmp(model->animscenes[i].name, name))
3126 PRVM_G_FLOAT(OFS_RETURN) = i;
3132 // #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.
3133 static void VM_SV_frameduration(void)
3135 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3136 dp_model_t *model = SV_GetModelByIndex(modelindex);
3137 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3138 PRVM_G_FLOAT(OFS_RETURN) = 0;
3139 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3141 if (model->animscenes[framenum].framerate)
3142 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3146 prvm_builtin_t vm_sv_builtins[] = {
3147 NULL, // #0 NULL function (not callable) (QUAKE)
3148 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3149 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3150 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3151 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3152 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3153 VM_break, // #6 void() break (QUAKE)
3154 VM_random, // #7 float() random (QUAKE)
3155 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3156 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3157 VM_error, // #10 void(string e) error (QUAKE)
3158 VM_objerror, // #11 void(string e) objerror (QUAKE)
3159 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3160 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3161 VM_spawn, // #14 entity() spawn (QUAKE)
3162 VM_remove, // #15 void(entity e) remove (QUAKE)
3163 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3164 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3165 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3166 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3167 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3168 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3169 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3170 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3171 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3172 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3173 VM_ftos, // #26 string(float f) ftos (QUAKE)
3174 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3175 VM_coredump, // #28 void() coredump (QUAKE)
3176 VM_traceon, // #29 void() traceon (QUAKE)
3177 VM_traceoff, // #30 void() traceoff (QUAKE)
3178 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3179 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3180 NULL, // #33 (QUAKE)
3181 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3182 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3183 VM_rint, // #36 float(float v) rint (QUAKE)
3184 VM_floor, // #37 float(float v) floor (QUAKE)
3185 VM_ceil, // #38 float(float v) ceil (QUAKE)
3186 NULL, // #39 (QUAKE)
3187 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3188 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3189 NULL, // #42 (QUAKE)
3190 VM_fabs, // #43 float(float f) fabs (QUAKE)
3191 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3192 VM_cvar, // #45 float(string s) cvar (QUAKE)
3193 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3194 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3195 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3196 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3197 NULL, // #50 (QUAKE)
3198 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3199 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3200 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3201 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3202 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3203 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3204 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3205 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3206 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3207 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3208 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3209 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3210 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3211 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3212 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3213 NULL, // #66 (QUAKE)
3214 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3215 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3216 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3217 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3218 NULL, // #71 (QUAKE)
3219 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3220 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3221 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3222 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3223 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3224 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3225 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3226 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3227 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3228 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3229 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3230 NULL, // #83 (QUAKE)
3231 NULL, // #84 (QUAKE)
3232 NULL, // #85 (QUAKE)
3233 NULL, // #86 (QUAKE)
3234 NULL, // #87 (QUAKE)
3235 NULL, // #88 (QUAKE)
3236 NULL, // #89 (QUAKE)
3237 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3238 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3239 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3240 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3241 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3242 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3243 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3244 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3245 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3246 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3247 // FrikaC and Telejano range #100-#199
3258 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3259 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3260 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3261 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3262 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3263 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3264 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3265 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3266 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3267 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3348 // FTEQW range #200-#299
3367 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3370 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3371 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3372 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3373 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3374 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3375 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3376 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3377 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3378 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3379 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3381 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3389 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3412 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.
3413 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
3414 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3415 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3416 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)
3417 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
3418 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)
3419 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)
3420 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)
3421 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)
3422 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)
3423 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
3424 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)
3425 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
3426 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.
3449 // CSQC range #300-#399
3450 NULL, // #300 void() clearscene (EXT_CSQC)
3451 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3452 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3453 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3454 NULL, // #304 void() renderscene (EXT_CSQC)
3455 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3456 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3457 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3458 NULL, // #308 void() R_EndPolygon
3460 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3461 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3465 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3466 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3467 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3468 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3469 NULL, // #319 void(string name) freepic (EXT_CSQC)
3470 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3471 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3472 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3473 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3474 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3475 NULL, // #325 void(void) drawresetcliparea
3480 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3481 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3482 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3483 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3484 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3485 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3486 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3487 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3488 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3489 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3490 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3491 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3492 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3493 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3494 NULL, // #344 vector() getmousepos (EXT_CSQC)
3495 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3496 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3497 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3498 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3499 NULL, // #349 float() isdemo (EXT_CSQC)
3500 VM_isserver, // #350 float() isserver (EXT_CSQC)
3501 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3502 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3503 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3504 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3510 NULL, // #360 float() readbyte (EXT_CSQC)
3511 NULL, // #361 float() readchar (EXT_CSQC)
3512 NULL, // #362 float() readshort (EXT_CSQC)
3513 NULL, // #363 float() readlong (EXT_CSQC)
3514 NULL, // #364 float() readcoord (EXT_CSQC)
3515 NULL, // #365 float() readangle (EXT_CSQC)
3516 NULL, // #366 string() readstring (EXT_CSQC)
3517 NULL, // #367 float() readfloat (EXT_CSQC)
3550 // LordHavoc's range #400-#499
3551 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3552 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3553 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3554 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3555 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3556 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3557 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3558 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3559 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)
3560 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3561 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3562 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3563 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3564 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3565 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3566 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3567 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3568 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3569 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3570 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3571 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3572 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3573 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3574 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3575 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3576 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3577 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3578 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3579 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3580 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3581 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3582 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3583 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3584 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3585 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3586 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3587 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3588 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3589 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3590 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3591 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3592 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3593 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3594 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3595 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3596 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3597 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3598 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3599 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3600 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3601 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3602 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3603 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3604 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3605 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3606 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3607 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3608 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3610 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3611 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3612 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3613 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3614 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3615 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3616 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3617 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3618 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3619 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3620 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3622 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3623 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3624 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3625 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3626 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3627 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3628 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3629 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3630 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3631 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3632 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3633 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3634 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3635 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3636 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3637 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3645 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3646 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3647 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3648 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3649 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3650 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3651 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3652 VM_SV_WritePicture, // #501
3654 VM_whichpack, // #503 string(string) whichpack = #503;
3661 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3662 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3663 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3664 VM_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET)
3665 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3666 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3667 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3668 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3669 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3670 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3680 VM_loadfromdata, // #529
3681 VM_loadfromfile, // #530
3682 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3756 VM_callfunction, // #605
3757 VM_writetofile, // #606
3758 VM_isfunction, // #607
3764 VM_parseentitydata, // #613
3775 VM_SV_getextresponse, // #624 string getextresponse(void)
3778 VM_sprintf, // #627 string sprintf(string format, ...)
3779 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3780 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3784 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3786 void VM_SV_Cmd_Init(void)
3791 void VM_SV_Cmd_Reset(void)
3793 World_End(&sv.world);
3794 if(prog->funcoffsets.SV_Shutdown)
3796 func_t s = prog->funcoffsets.SV_Shutdown;
3797 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3798 PRVM_ExecuteProgram(s,"SV_Shutdown() required");