6 //============================================================================
11 char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
22 "DP_CSQC_MULTIFRAME_INTERPOLATION "
38 "DP_ENT_CUSTOMCOLORMAP "
39 "DP_ENT_EXTERIORMODELTOCLIENT "
41 "DP_ENT_LOWPRECISION "
45 "DP_GFX_EXTERNALTEXTURES "
46 "DP_GFX_EXTERNALTEXTURES_PERMAP "
48 "DP_GFX_QUAKE3MODELTAGS "
51 "DP_GFX_MODEL_INTERPOLATION "
53 "DP_HALFLIFE_MAP_CVAR "
59 "DP_MOVETYPEBOUNCEMISSILE "
62 "DP_QC_ASINACOSATANATAN2TAN "
67 "DP_QC_CVAR_DEFSTRING "
68 "DP_QC_CVAR_DESCRIPTION "
74 "DP_QC_EXTRESPONSEPACKET "
76 "DP_QC_FINDCHAIN_TOFIELD "
77 "DP_QC_FINDCHAINFLAGS "
78 "DP_QC_FINDCHAINFLOAT "
84 "DP_QC_GETSURFACEPOINTATTRIBUTE "
86 "DP_QC_GETTAGINFO_BONEPROPERTIES "
88 "DP_QC_GETTIME_CDTRACK "
90 "DP_QC_MULTIPLETEMPSTRINGS "
91 "DP_QC_NUM_FOR_EDICT "
93 "DP_QC_SINCOSSQRTPOW "
95 "DP_QC_STRINGBUFFERS "
96 "DP_QC_STRINGBUFFERS_CVARLIST "
97 "DP_QC_STRINGCOLORFUNCTIONS "
98 "DP_QC_STRING_CASE_FUNCTIONS "
100 "DP_QC_TOKENIZEBYSEPARATOR "
101 "DP_QC_TOKENIZE_CONSOLE "
104 "DP_QC_TRACE_MOVETYPE_HITMODEL "
105 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
106 "DP_QC_UNLIMITEDTEMPSTRINGS "
109 "DP_QC_VECTOANGLES_WITH_ROLL "
110 "DP_QC_VECTORVECTORS "
117 "DP_SND_DIRECTIONLESSATTNNONE "
124 "DP_SV_BOUNCEFACTOR "
125 "DP_SV_CLIENTCOLORS "
128 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
129 "DP_SV_DRAWONLYTOCLIENT "
132 "DP_SV_ENTITYCONTENTSTRANSITION "
133 "DP_SV_MODELFLAGS_AS_EFFECTS "
134 "DP_SV_MOVETYPESTEP_LANDEVENT "
136 "DP_SV_NODRAWTOCLIENT "
137 "DP_SV_ONENTITYNOSPAWNFUNCTION "
138 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
140 "DP_SV_PLAYERPHYSICS "
141 "DP_SV_POINTPARTICLES "
143 "DP_SV_PRECACHEANYTIME "
147 "DP_SV_ROTATINGBMODEL "
151 "DP_SV_SPAWNFUNC_PREFIX "
152 "DP_SV_WRITEPICTURE "
153 "DP_SV_WRITEUNTERMINATEDSTRING "
157 "DP_TE_EXPLOSIONRGB "
159 "DP_TE_PARTICLECUBE "
160 "DP_TE_PARTICLERAIN "
161 "DP_TE_PARTICLESNOW "
163 "DP_TE_QUADEFFECTS1 "
166 "DP_TE_STANDARDEFFECTBUILTINS "
167 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
173 "KRIMZON_SV_PARSECLIENTCOMMAND "
176 "NEXUIZ_PLAYERMODEL "
178 "PRYDON_CLIENTCURSOR "
179 "TENEBRAE_GFX_DLIGHTS "
182 //"EXT_CSQC " // not ready yet
189 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.
191 setorigin (entity, origin)
194 static void VM_SV_setorigin (void)
199 VM_SAFEPARMCOUNT(2, VM_setorigin);
201 e = PRVM_G_EDICT(OFS_PARM0);
202 if (e == prog->edicts)
204 VM_Warning("setorigin: can not modify world entity\n");
207 if (e->priv.server->free)
209 VM_Warning("setorigin: can not modify free entity\n");
212 org = PRVM_G_VECTOR(OFS_PARM1);
213 VectorCopy (org, e->fields.server->origin);
214 SV_LinkEdict (e, false);
217 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
218 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
222 for (i=0 ; i<3 ; i++)
224 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
226 // set derived values
227 VectorCopy (min, e->fields.server->mins);
228 VectorCopy (max, e->fields.server->maxs);
229 VectorSubtract (max, min, e->fields.server->size);
231 SV_LinkEdict (e, false);
238 the size box is rotated by the current angle
239 LordHavoc: no it isn't...
241 setsize (entity, minvector, maxvector)
244 static void VM_SV_setsize (void)
249 VM_SAFEPARMCOUNT(3, VM_setsize);
251 e = PRVM_G_EDICT(OFS_PARM0);
252 if (e == prog->edicts)
254 VM_Warning("setsize: can not modify world entity\n");
257 if (e->priv.server->free)
259 VM_Warning("setsize: can not modify free entity\n");
262 min = PRVM_G_VECTOR(OFS_PARM1);
263 max = PRVM_G_VECTOR(OFS_PARM2);
264 SetMinMaxSize (e, min, max, false);
272 setmodel(entity, model)
275 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
276 static void VM_SV_setmodel (void)
282 VM_SAFEPARMCOUNT(2, VM_setmodel);
284 e = PRVM_G_EDICT(OFS_PARM0);
285 if (e == prog->edicts)
287 VM_Warning("setmodel: can not modify world entity\n");
290 if (e->priv.server->free)
292 VM_Warning("setmodel: can not modify free entity\n");
295 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
296 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
297 e->fields.server->modelindex = i;
303 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
304 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
306 SetMinMaxSize (e, quakemins, quakemaxs, true);
309 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
316 single print to a specific client
318 sprint(clientent, value)
321 static void VM_SV_sprint (void)
325 char string[VM_STRINGTEMP_LENGTH];
327 VM_VarString(1, string, sizeof(string));
329 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
331 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
332 // LordHavoc: div0 requested that sprintto world operate like print
339 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
341 VM_Warning("tried to centerprint to a non-client\n");
345 client = svs.clients + entnum-1;
346 if (!client->netconnection)
349 MSG_WriteChar(&client->netconnection->message,svc_print);
350 MSG_WriteString(&client->netconnection->message, string);
358 single print to a specific client
360 centerprint(clientent, value)
363 static void VM_SV_centerprint (void)
367 char string[VM_STRINGTEMP_LENGTH];
369 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
371 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
373 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
375 VM_Warning("tried to centerprint to a non-client\n");
379 client = svs.clients + entnum-1;
380 if (!client->netconnection)
383 VM_VarString(1, string, sizeof(string));
384 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
385 MSG_WriteString(&client->netconnection->message, string);
392 particle(origin, color, count)
395 static void VM_SV_particle (void)
401 VM_SAFEPARMCOUNT(4, VM_SV_particle);
403 org = PRVM_G_VECTOR(OFS_PARM0);
404 dir = PRVM_G_VECTOR(OFS_PARM1);
405 color = PRVM_G_FLOAT(OFS_PARM2);
406 count = PRVM_G_FLOAT(OFS_PARM3);
407 SV_StartParticle (org, dir, (int)color, (int)count);
417 static void VM_SV_ambientsound (void)
421 float vol, attenuation;
424 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
426 pos = PRVM_G_VECTOR (OFS_PARM0);
427 samp = PRVM_G_STRING(OFS_PARM1);
428 vol = PRVM_G_FLOAT(OFS_PARM2);
429 attenuation = PRVM_G_FLOAT(OFS_PARM3);
431 // check to see if samp was properly precached
432 soundnum = SV_SoundIndex(samp, 1);
440 // add an svc_spawnambient command to the level signon packet
443 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
445 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
447 MSG_WriteVector(&sv.signon, pos, sv.protocol);
449 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
450 MSG_WriteShort (&sv.signon, soundnum);
452 MSG_WriteByte (&sv.signon, soundnum);
454 MSG_WriteByte (&sv.signon, (int)(vol*255));
455 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
463 Each entity can have eight independant sound sources, like voice,
466 Channel 0 is an auto-allocate channel, the others override anything
467 already running on that entity/channel pair.
469 An attenuation of 0 will play full volume everywhere in the level.
470 Larger attenuations will drop off.
474 static void VM_SV_sound (void)
478 prvm_edict_t *entity;
482 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
484 entity = PRVM_G_EDICT(OFS_PARM0);
485 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
486 sample = PRVM_G_STRING(OFS_PARM2);
487 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
488 attenuation = PRVM_G_FLOAT(OFS_PARM4);
491 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
495 if (volume < 0 || volume > 255)
497 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
501 if (attenuation < 0 || attenuation > 4)
503 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
507 if (channel < 0 || channel > 7)
509 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
513 SV_StartSound (entity, channel, sample, volume, attenuation);
520 Follows the same logic as VM_SV_sound, except instead of
521 an entity, an origin for the sound is provided, and channel
522 is omitted (since no entity is being tracked).
526 static void VM_SV_pointsound(void)
533 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
535 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
536 sample = PRVM_G_STRING(OFS_PARM1);
537 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
538 attenuation = PRVM_G_FLOAT(OFS_PARM3);
540 if (volume < 0 || volume > 255)
542 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
546 if (attenuation < 0 || attenuation > 4)
548 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
552 SV_StartPointSound (org, sample, volume, attenuation);
559 Used for use tracing and shot targeting
560 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
561 if the tryents flag is set.
563 traceline (vector1, vector2, movetype, ignore)
566 static void VM_SV_traceline (void)
573 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
575 prog->xfunction->builtinsprofile += 30;
577 v1 = PRVM_G_VECTOR(OFS_PARM0);
578 v2 = PRVM_G_VECTOR(OFS_PARM1);
579 move = (int)PRVM_G_FLOAT(OFS_PARM2);
580 ent = PRVM_G_EDICT(OFS_PARM3);
582 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]))
583 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));
585 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
587 VM_SetTraceGlobals(&trace);
595 Used for use tracing and shot targeting
596 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
597 if the tryents flag is set.
599 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
602 // LordHavoc: added this for my own use, VERY useful, similar to traceline
603 static void VM_SV_tracebox (void)
605 float *v1, *v2, *m1, *m2;
610 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
612 prog->xfunction->builtinsprofile += 30;
614 v1 = PRVM_G_VECTOR(OFS_PARM0);
615 m1 = PRVM_G_VECTOR(OFS_PARM1);
616 m2 = PRVM_G_VECTOR(OFS_PARM2);
617 v2 = PRVM_G_VECTOR(OFS_PARM3);
618 move = (int)PRVM_G_FLOAT(OFS_PARM4);
619 ent = PRVM_G_EDICT(OFS_PARM5);
621 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]))
622 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));
624 trace = SV_Move (v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
626 VM_SetTraceGlobals(&trace);
629 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
634 vec3_t original_origin;
635 vec3_t original_velocity;
636 vec3_t original_angles;
637 vec3_t original_avelocity;
641 VectorCopy(tossent->fields.server->origin , original_origin );
642 VectorCopy(tossent->fields.server->velocity , original_velocity );
643 VectorCopy(tossent->fields.server->angles , original_angles );
644 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
646 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
647 if (val != NULL && val->_float != 0)
648 gravity = val->_float;
651 gravity *= sv_gravity.value * 0.025;
653 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
655 SV_CheckVelocity (tossent);
656 tossent->fields.server->velocity[2] -= gravity;
657 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
658 VectorScale (tossent->fields.server->velocity, 0.05, move);
659 VectorAdd (tossent->fields.server->origin, move, end);
660 trace = SV_Move (tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
661 VectorCopy (trace.endpos, tossent->fields.server->origin);
662 tossent->fields.server->velocity[2] -= gravity;
664 if (trace.fraction < 1)
668 VectorCopy(original_origin , tossent->fields.server->origin );
669 VectorCopy(original_velocity , tossent->fields.server->velocity );
670 VectorCopy(original_angles , tossent->fields.server->angles );
671 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
676 static void VM_SV_tracetoss (void)
680 prvm_edict_t *ignore;
682 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
684 prog->xfunction->builtinsprofile += 600;
686 ent = PRVM_G_EDICT(OFS_PARM0);
687 if (ent == prog->edicts)
689 VM_Warning("tracetoss: can not use world entity\n");
692 ignore = PRVM_G_EDICT(OFS_PARM1);
694 trace = SV_Trace_Toss (ent, ignore);
696 VM_SetTraceGlobals(&trace);
699 //============================================================================
701 static int checkpvsbytes;
702 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
704 static int VM_SV_newcheckclient (int check)
710 // cycle to the next one
712 check = bound(1, check, svs.maxclients);
713 if (check == svs.maxclients)
721 prog->xfunction->builtinsprofile++;
723 if (i == svs.maxclients+1)
725 // look up the client's edict
726 ent = PRVM_EDICT_NUM(i);
727 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
728 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
730 // found a valid client (possibly the same one again)
734 // get the PVS for the entity
735 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
737 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
738 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
747 Returns a client (or object that has a client enemy) that would be a
750 If there is more than one valid option, they are cycled each frame
752 If (self.origin + self.viewofs) is not in the PVS of the current target,
753 it is not returned at all.
758 int c_invis, c_notvis;
759 static void VM_SV_checkclient (void)
761 prvm_edict_t *ent, *self;
764 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
766 // find a new check if on a new frame
767 if (sv.time - sv.lastchecktime >= 0.1)
769 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
770 sv.lastchecktime = sv.time;
773 // return check if it might be visible
774 ent = PRVM_EDICT_NUM(sv.lastcheck);
775 if (ent->priv.server->free || ent->fields.server->health <= 0)
777 VM_RETURN_EDICT(prog->edicts);
781 // if current entity can't possibly see the check entity, return 0
782 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
783 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
784 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
787 VM_RETURN_EDICT(prog->edicts);
791 // might be able to see it
793 VM_RETURN_EDICT(ent);
796 //============================================================================
802 Checks if an entity is in a point's PVS.
803 Should be fast but can be inexact.
805 float checkpvs(vector viewpos, entity viewee) = #240;
808 static void VM_SV_checkpvs (void)
811 prvm_edict_t *viewee;
815 static int fatpvsbytes;
816 static unsigned char fatpvs[MAX_MAP_LEAFS/8];
819 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
820 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
821 viewee = PRVM_G_EDICT(OFS_PARM1);
823 if(viewee->priv.server->free)
825 VM_Warning("checkpvs: can not check free entity\n");
826 PRVM_G_FLOAT(OFS_RETURN) = 4;
831 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
833 // no PVS support on this worldmodel... darn
834 PRVM_G_FLOAT(OFS_RETURN) = 3;
837 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
840 // viewpos isn't in any PVS... darn
841 PRVM_G_FLOAT(OFS_RETURN) = 2;
844 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
846 // using fat PVS like FTEQW does (slow)
847 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
849 // no PVS support on this worldmodel... darn
850 PRVM_G_FLOAT(OFS_RETURN) = 3;
853 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
856 // viewpos isn't in any PVS... darn
857 PRVM_G_FLOAT(OFS_RETURN) = 2;
860 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
869 Sends text over to the client's execution buffer
871 stuffcmd (clientent, value, ...)
874 static void VM_SV_stuffcmd (void)
878 char string[VM_STRINGTEMP_LENGTH];
880 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
882 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
883 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
885 VM_Warning("Can't stuffcmd to a non-client\n");
889 VM_VarString(1, string, sizeof(string));
892 host_client = svs.clients + entnum-1;
893 Host_ClientCommands ("%s", string);
901 Returns a chain of entities that have origins within a spherical area
903 findradius (origin, radius)
906 static void VM_SV_findradius (void)
908 prvm_edict_t *ent, *chain;
909 vec_t radius, radius2;
910 vec3_t org, eorg, mins, maxs;
913 prvm_edict_t *touchedicts[MAX_EDICTS];
916 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
919 chainfield = PRVM_G_INT(OFS_PARM2);
921 chainfield = prog->fieldoffsets.chain;
923 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
925 chain = (prvm_edict_t *)prog->edicts;
927 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
928 radius = PRVM_G_FLOAT(OFS_PARM1);
929 radius2 = radius * radius;
931 mins[0] = org[0] - (radius + 1);
932 mins[1] = org[1] - (radius + 1);
933 mins[2] = org[2] - (radius + 1);
934 maxs[0] = org[0] + (radius + 1);
935 maxs[1] = org[1] + (radius + 1);
936 maxs[2] = org[2] + (radius + 1);
937 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
938 if (numtouchedicts > MAX_EDICTS)
940 // this never happens
941 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
942 numtouchedicts = MAX_EDICTS;
944 for (i = 0;i < numtouchedicts;i++)
946 ent = touchedicts[i];
947 prog->xfunction->builtinsprofile++;
948 // Quake did not return non-solid entities but darkplaces does
949 // (note: this is the reason you can't blow up fallen zombies)
950 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
952 // LordHavoc: compare against bounding box rather than center so it
953 // doesn't miss large objects, and use DotProduct instead of Length
954 // for a major speedup
955 VectorSubtract(org, ent->fields.server->origin, eorg);
956 if (sv_gameplayfix_findradiusdistancetobox.integer)
958 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
959 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
960 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
963 VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
964 if (DotProduct(eorg, eorg) < radius2)
966 PRVM_EDICTFIELDVALUE(ent,chainfield)->edict = PRVM_EDICT_TO_PROG(chain);
971 VM_RETURN_EDICT(chain);
974 static void VM_SV_precache_sound (void)
976 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
977 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
980 static void VM_SV_precache_model (void)
982 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
983 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
984 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
991 float(float yaw, float dist[, settrace]) walkmove
994 static void VM_SV_walkmove (void)
1003 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1005 // assume failure if it returns early
1006 PRVM_G_FLOAT(OFS_RETURN) = 0;
1008 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1009 if (ent == prog->edicts)
1011 VM_Warning("walkmove: can not modify world entity\n");
1014 if (ent->priv.server->free)
1016 VM_Warning("walkmove: can not modify free entity\n");
1019 yaw = PRVM_G_FLOAT(OFS_PARM0);
1020 dist = PRVM_G_FLOAT(OFS_PARM1);
1021 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1023 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1026 yaw = yaw*M_PI*2 / 360;
1028 move[0] = cos(yaw)*dist;
1029 move[1] = sin(yaw)*dist;
1032 // save program state, because SV_movestep may call other progs
1033 oldf = prog->xfunction;
1034 oldself = prog->globals.server->self;
1036 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1039 // restore program state
1040 prog->xfunction = oldf;
1041 prog->globals.server->self = oldself;
1051 static void VM_SV_droptofloor (void)
1057 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1059 // assume failure if it returns early
1060 PRVM_G_FLOAT(OFS_RETURN) = 0;
1062 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1063 if (ent == prog->edicts)
1065 VM_Warning("droptofloor: can not modify world entity\n");
1068 if (ent->priv.server->free)
1070 VM_Warning("droptofloor: can not modify free entity\n");
1074 VectorCopy (ent->fields.server->origin, end);
1077 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1078 SV_UnstickEntity(ent);
1080 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1081 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1084 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]);
1085 VectorAdd(ent->fields.server->origin, offset, org);
1086 trace = SV_Move (org, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1087 VectorSubtract(trace.endpos, offset, trace.endpos);
1088 if (trace.startsolid)
1090 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]);
1091 SV_UnstickEntity(ent);
1092 SV_LinkEdict (ent, false);
1093 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1094 ent->fields.server->groundentity = 0;
1095 PRVM_G_FLOAT(OFS_RETURN) = 1;
1097 else if (trace.fraction < 1)
1099 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]);
1100 VectorCopy (trace.endpos, ent->fields.server->origin);
1101 SV_UnstickEntity(ent);
1102 SV_LinkEdict (ent, false);
1103 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1104 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1105 PRVM_G_FLOAT(OFS_RETURN) = 1;
1106 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1107 ent->priv.server->suspendedinairflag = true;
1112 if (trace.fraction != 1)
1114 if (trace.fraction < 1)
1115 VectorCopy (trace.endpos, ent->fields.server->origin);
1116 SV_LinkEdict (ent, false);
1117 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1118 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1119 PRVM_G_FLOAT(OFS_RETURN) = 1;
1120 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1121 ent->priv.server->suspendedinairflag = true;
1130 void(float style, string value) lightstyle
1133 static void VM_SV_lightstyle (void)
1140 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1142 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1143 val = PRVM_G_STRING(OFS_PARM1);
1145 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1146 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1149 // change the string in sv
1150 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1152 // send message to all clients on this server
1153 if (sv.state != ss_active)
1156 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1158 if (client->active && client->netconnection)
1160 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1161 MSG_WriteChar (&client->netconnection->message,style);
1162 MSG_WriteString (&client->netconnection->message, val);
1172 static void VM_SV_checkbottom (void)
1174 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1175 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1183 static void VM_SV_pointcontents (void)
1185 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1186 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1193 Pick a vector for the player to shoot along
1194 vector aim(entity, missilespeed)
1197 static void VM_SV_aim (void)
1199 prvm_edict_t *ent, *check, *bestent;
1200 vec3_t start, dir, end, bestdir;
1203 float dist, bestdist;
1206 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1208 // assume failure if it returns early
1209 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1210 // if sv_aim is so high it can't possibly accept anything, skip out early
1211 if (sv_aim.value >= 1)
1214 ent = PRVM_G_EDICT(OFS_PARM0);
1215 if (ent == prog->edicts)
1217 VM_Warning("aim: can not use world entity\n");
1220 if (ent->priv.server->free)
1222 VM_Warning("aim: can not use free entity\n");
1225 speed = PRVM_G_FLOAT(OFS_PARM1);
1227 VectorCopy (ent->fields.server->origin, start);
1230 // try sending a trace straight
1231 VectorCopy (prog->globals.server->v_forward, dir);
1232 VectorMA (start, 2048, dir, end);
1233 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1234 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1235 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1237 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1242 // try all possible entities
1243 VectorCopy (dir, bestdir);
1244 bestdist = sv_aim.value;
1247 check = PRVM_NEXT_EDICT(prog->edicts);
1248 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1250 prog->xfunction->builtinsprofile++;
1251 if (check->fields.server->takedamage != DAMAGE_AIM)
1255 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1256 continue; // don't aim at teammate
1257 for (j=0 ; j<3 ; j++)
1258 end[j] = check->fields.server->origin[j]
1259 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1260 VectorSubtract (end, start, dir);
1261 VectorNormalize (dir);
1262 dist = DotProduct (dir, prog->globals.server->v_forward);
1263 if (dist < bestdist)
1264 continue; // to far to turn
1265 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1266 if (tr.ent == check)
1267 { // can shoot at this one
1275 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1276 dist = DotProduct (dir, prog->globals.server->v_forward);
1277 VectorScale (prog->globals.server->v_forward, dist, end);
1279 VectorNormalize (end);
1280 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1284 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1289 ===============================================================================
1293 ===============================================================================
1296 #define MSG_BROADCAST 0 // unreliable to all
1297 #define MSG_ONE 1 // reliable to one (msg_entity)
1298 #define MSG_ALL 2 // reliable to all
1299 #define MSG_INIT 3 // write to the init string
1300 #define MSG_ENTITY 5
1302 sizebuf_t *WriteDest (void)
1308 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1312 return &sv.datagram;
1315 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1316 entnum = PRVM_NUM_FOR_EDICT(ent);
1317 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1319 VM_Warning ("WriteDest: tried to write to non-client\n");
1320 return &sv.reliable_datagram;
1323 return &svs.clients[entnum-1].netconnection->message;
1326 VM_Warning ("WriteDest: bad destination\n");
1328 return &sv.reliable_datagram;
1334 return sv.writeentitiestoclient_msg;
1340 static void VM_SV_WriteByte (void)
1342 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1343 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1346 static void VM_SV_WriteChar (void)
1348 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1349 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1352 static void VM_SV_WriteShort (void)
1354 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1355 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1358 static void VM_SV_WriteLong (void)
1360 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1361 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1364 static void VM_SV_WriteAngle (void)
1366 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1367 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1370 static void VM_SV_WriteCoord (void)
1372 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1373 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1376 static void VM_SV_WriteString (void)
1378 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1379 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1382 static void VM_SV_WriteUnterminatedString (void)
1384 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1385 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1389 static void VM_SV_WriteEntity (void)
1391 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1392 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1395 // writes a picture as at most size bytes of data
1397 // IMGNAME \0 SIZE(short) IMGDATA
1398 // if failed to read/compress:
1400 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1401 static void VM_SV_WritePicture (void)
1403 const char *imgname;
1407 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1409 imgname = PRVM_G_STRING(OFS_PARM1);
1410 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1414 MSG_WriteString(WriteDest(), imgname);
1415 if(Image_Compress(imgname, size, &buf, &size))
1418 MSG_WriteShort(WriteDest(), size);
1419 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1424 MSG_WriteShort(WriteDest(), 0);
1428 //////////////////////////////////////////////////////////
1430 static void VM_SV_makestatic (void)
1435 // allow 0 parameters due to an id1 qc bug in which this function is used
1436 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1437 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1439 if (prog->argc >= 1)
1440 ent = PRVM_G_EDICT(OFS_PARM0);
1442 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1443 if (ent == prog->edicts)
1445 VM_Warning("makestatic: can not modify world entity\n");
1448 if (ent->priv.server->free)
1450 VM_Warning("makestatic: can not modify free entity\n");
1455 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1460 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1461 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1462 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1464 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1466 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1467 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1468 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1472 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1473 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1474 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1477 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1478 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1479 for (i=0 ; i<3 ; i++)
1481 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1482 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1485 // throw the entity away now
1489 //=============================================================================
1496 static void VM_SV_setspawnparms (void)
1502 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1504 ent = PRVM_G_EDICT(OFS_PARM0);
1505 i = PRVM_NUM_FOR_EDICT(ent);
1506 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1508 Con_Print("tried to setspawnparms on a non-client\n");
1512 // copy spawn parms out of the client_t
1513 client = svs.clients + i-1;
1514 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1515 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1522 Returns a color vector indicating the lighting at the requested point.
1524 (Internal Operation note: actually measures the light beneath the point, just like
1525 the model lighting on the client)
1530 static void VM_SV_getlight (void)
1532 vec3_t ambientcolor, diffusecolor, diffusenormal;
1534 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1535 p = PRVM_G_VECTOR(OFS_PARM0);
1536 VectorClear(ambientcolor);
1537 VectorClear(diffusecolor);
1538 VectorClear(diffusenormal);
1539 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1540 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1541 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1546 unsigned char type; // 1/2/8 or other value if isn't used
1550 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1551 static int vm_customstats_last;
1553 void VM_CustomStats_Clear (void)
1557 Z_Free(vm_customstats);
1558 vm_customstats = NULL;
1559 vm_customstats_last = -1;
1563 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1571 for(i=0; i<vm_customstats_last+1 ;i++)
1573 if(!vm_customstats[i].type)
1575 switch(vm_customstats[i].type)
1577 //string as 16 bytes
1580 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1581 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1582 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1583 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1584 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1586 //float field sent as-is
1588 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1590 //integer value of float field
1592 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1600 // void(float index, float type, .void field) SV_AddStat = #232;
1601 // Set up an auto-sent player stat.
1602 // Client's get thier own fields sent to them. Index may not be less than 32.
1603 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1604 // 1: string (4 stats carrying a total of 16 charactures)
1605 // 2: float (one stat, float converted to an integer for transportation)
1606 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1607 static void VM_SV_AddStat (void)
1612 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1616 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1619 VM_Warning("PF_SV_AddStat: not enough memory\n");
1623 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1624 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1625 off = PRVM_G_INT (OFS_PARM2);
1630 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1633 if(i >= (MAX_CL_STATS-32))
1635 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1638 if(i > (MAX_CL_STATS-32-4) && type == 1)
1640 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1643 vm_customstats[i].type = type;
1644 vm_customstats[i].fieldoffset = off;
1645 if(vm_customstats_last < i)
1646 vm_customstats_last = i;
1653 copies data from one entity to another
1655 copyentity(src, dst)
1658 static void VM_SV_copyentity (void)
1660 prvm_edict_t *in, *out;
1661 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1662 in = PRVM_G_EDICT(OFS_PARM0);
1663 if (in == prog->edicts)
1665 VM_Warning("copyentity: can not read world entity\n");
1668 if (in->priv.server->free)
1670 VM_Warning("copyentity: can not read free entity\n");
1673 out = PRVM_G_EDICT(OFS_PARM1);
1674 if (out == prog->edicts)
1676 VM_Warning("copyentity: can not modify world entity\n");
1679 if (out->priv.server->free)
1681 VM_Warning("copyentity: can not modify free entity\n");
1684 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1685 SV_LinkEdict(out, false);
1693 sets the color of a client and broadcasts the update to all connected clients
1695 setcolor(clientent, value)
1698 static void VM_SV_setcolor (void)
1704 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1705 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1706 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1708 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1710 Con_Print("tried to setcolor a non-client\n");
1714 client = svs.clients + entnum-1;
1717 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1719 client->edict->fields.server->team = (i & 15) + 1;
1722 if (client->old_colors != client->colors)
1724 client->old_colors = client->colors;
1725 // send notification to all clients
1726 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1727 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1728 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1736 effect(origin, modelname, startframe, framecount, framerate)
1739 static void VM_SV_effect (void)
1743 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1744 s = PRVM_G_STRING(OFS_PARM1);
1747 VM_Warning("effect: no model specified\n");
1751 i = SV_ModelIndex(s, 1);
1754 VM_Warning("effect: model not precached\n");
1758 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1760 VM_Warning("effect: framecount < 1\n");
1764 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1766 VM_Warning("effect: framerate < 1\n");
1770 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));
1773 static void VM_SV_te_blood (void)
1775 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1776 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1778 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1779 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1781 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1782 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1783 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1785 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1786 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1787 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1789 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1790 SV_FlushBroadcastMessages();
1793 static void VM_SV_te_bloodshower (void)
1795 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1796 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1798 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1799 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1801 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1802 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1803 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1805 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1809 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1811 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1812 SV_FlushBroadcastMessages();
1815 static void VM_SV_te_explosionrgb (void)
1817 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1818 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1819 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1821 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1822 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1823 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1825 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1826 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1827 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1828 SV_FlushBroadcastMessages();
1831 static void VM_SV_te_particlecube (void)
1833 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1834 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1836 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1837 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1839 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1840 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1841 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1843 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1844 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1845 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1847 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1848 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1849 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1851 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1853 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1854 // gravity true/false
1855 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1857 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1858 SV_FlushBroadcastMessages();
1861 static void VM_SV_te_particlerain (void)
1863 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1864 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1866 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1867 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1869 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1870 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1873 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1874 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1875 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1877 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1878 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1879 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1881 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1883 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1884 SV_FlushBroadcastMessages();
1887 static void VM_SV_te_particlesnow (void)
1889 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1890 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1892 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1893 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1895 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1896 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1900 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1907 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1909 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1910 SV_FlushBroadcastMessages();
1913 static void VM_SV_te_spark (void)
1915 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1916 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1918 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1919 MSG_WriteByte(&sv.datagram, TE_SPARK);
1921 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1922 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1923 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1925 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1926 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1927 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1929 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1930 SV_FlushBroadcastMessages();
1933 static void VM_SV_te_gunshotquad (void)
1935 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1936 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1937 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1941 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1942 SV_FlushBroadcastMessages();
1945 static void VM_SV_te_spikequad (void)
1947 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1948 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1949 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1952 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1953 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1954 SV_FlushBroadcastMessages();
1957 static void VM_SV_te_superspikequad (void)
1959 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1960 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1961 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1964 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1965 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1966 SV_FlushBroadcastMessages();
1969 static void VM_SV_te_explosionquad (void)
1971 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
1972 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1973 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1975 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1976 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1977 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1978 SV_FlushBroadcastMessages();
1981 static void VM_SV_te_smallflash (void)
1983 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
1984 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1985 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1989 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1990 SV_FlushBroadcastMessages();
1993 static void VM_SV_te_customflash (void)
1995 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
1996 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1998 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1999 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2001 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2002 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2005 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2007 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2009 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2010 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2011 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2012 SV_FlushBroadcastMessages();
2015 static void VM_SV_te_gunshot (void)
2017 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2018 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2019 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2021 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2022 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2023 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2024 SV_FlushBroadcastMessages();
2027 static void VM_SV_te_spike (void)
2029 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2030 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2031 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2033 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2034 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2035 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2036 SV_FlushBroadcastMessages();
2039 static void VM_SV_te_superspike (void)
2041 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2042 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2043 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2045 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2046 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2047 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2048 SV_FlushBroadcastMessages();
2051 static void VM_SV_te_explosion (void)
2053 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2054 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2055 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2058 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2059 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2060 SV_FlushBroadcastMessages();
2063 static void VM_SV_te_tarexplosion (void)
2065 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2066 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2067 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2069 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2070 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2071 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2072 SV_FlushBroadcastMessages();
2075 static void VM_SV_te_wizspike (void)
2077 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2078 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2079 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2081 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2082 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2083 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2084 SV_FlushBroadcastMessages();
2087 static void VM_SV_te_knightspike (void)
2089 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2090 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2091 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2093 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2094 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2095 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2096 SV_FlushBroadcastMessages();
2099 static void VM_SV_te_lavasplash (void)
2101 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2102 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2103 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2105 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2106 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2107 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2108 SV_FlushBroadcastMessages();
2111 static void VM_SV_te_teleport (void)
2113 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2114 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2115 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2117 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2118 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2119 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2120 SV_FlushBroadcastMessages();
2123 static void VM_SV_te_explosion2 (void)
2125 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2126 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2127 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2129 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2130 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2131 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2133 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2134 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2135 SV_FlushBroadcastMessages();
2138 static void VM_SV_te_lightning1 (void)
2140 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2141 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2142 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2144 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2146 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2147 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2148 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2150 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2151 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2152 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2153 SV_FlushBroadcastMessages();
2156 static void VM_SV_te_lightning2 (void)
2158 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2159 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2160 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2162 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2164 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2165 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2166 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2168 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2169 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2170 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2171 SV_FlushBroadcastMessages();
2174 static void VM_SV_te_lightning3 (void)
2176 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2177 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2178 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2180 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2182 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2183 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2184 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2186 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2187 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2188 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2189 SV_FlushBroadcastMessages();
2192 static void VM_SV_te_beam (void)
2194 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2195 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2196 MSG_WriteByte(&sv.datagram, TE_BEAM);
2198 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2200 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2201 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2202 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2204 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2205 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2206 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2207 SV_FlushBroadcastMessages();
2210 static void VM_SV_te_plasmaburn (void)
2212 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2213 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2214 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2215 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2216 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2217 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2218 SV_FlushBroadcastMessages();
2221 static void VM_SV_te_flamejet (void)
2223 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2224 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2225 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2227 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2231 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2232 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2235 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2236 SV_FlushBroadcastMessages();
2239 void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2242 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2244 bestdist = 1000000000;
2246 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2248 // clip original point to each triangle of the surface and find the
2249 // triangle that is closest
2250 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2251 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2252 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2253 TriangleNormal(v[0], v[1], v[2], facenormal);
2254 VectorNormalize(facenormal);
2255 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2256 VectorMA(p, offsetdist, facenormal, temp);
2257 for (j = 0, k = 2;j < 3;k = j, j++)
2259 VectorSubtract(v[k], v[j], edgenormal);
2260 CrossProduct(edgenormal, facenormal, sidenormal);
2261 VectorNormalize(sidenormal);
2262 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2264 VectorMA(temp, offsetdist, sidenormal, temp);
2266 dist = VectorDistance2(temp, p);
2267 if (bestdist > dist)
2270 VectorCopy(temp, out);
2275 static dp_model_t *getmodel(prvm_edict_t *ed)
2278 if (!ed || ed->priv.server->free)
2280 modelindex = (int)ed->fields.server->modelindex;
2281 if (modelindex < 1 || modelindex >= MAX_MODELS)
2283 return sv.models[modelindex];
2286 static msurface_t *getsurface(dp_model_t *model, int surfacenum)
2288 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2290 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2294 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2295 static void VM_SV_getsurfacenumpoints(void)
2298 msurface_t *surface;
2299 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints);
2300 // return 0 if no such surface
2301 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2303 PRVM_G_FLOAT(OFS_RETURN) = 0;
2307 // note: this (incorrectly) assumes it is a simple polygon
2308 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2310 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2311 static void VM_SV_getsurfacepoint(void)
2315 msurface_t *surface;
2317 VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint);
2318 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2319 ed = PRVM_G_EDICT(OFS_PARM0);
2320 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2322 // note: this (incorrectly) assumes it is a simple polygon
2323 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2324 if (pointnum < 0 || pointnum >= surface->num_vertices)
2326 // FIXME: implement rotation/scaling
2327 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2329 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
2330 // float SPA_POSITION = 0;
2331 // float SPA_S_AXIS = 1;
2332 // float SPA_T_AXIS = 2;
2333 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2334 // float SPA_TEXCOORDS0 = 4;
2335 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2336 // float SPA_LIGHTMAP0_COLOR = 6;
2337 static void VM_SV_getsurfacepointattribute(void)
2341 msurface_t *surface;
2345 VM_SAFEPARMCOUNT(4, VM_SV_getsurfacepoint);
2346 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2347 ed = PRVM_G_EDICT(OFS_PARM0);
2348 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2350 // note: this (incorrectly) assumes it is a simple polygon
2351 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2352 if (pointnum < 0 || pointnum >= surface->num_vertices)
2354 // FIXME: implement rotation/scaling
2355 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
2357 switch( attributetype ) {
2358 // float SPA_POSITION = 0;
2360 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2362 // float SPA_S_AXIS = 1;
2364 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2366 // float SPA_T_AXIS = 2;
2368 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2370 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2372 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2374 // float SPA_TEXCOORDS0 = 4;
2376 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2377 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
2378 ret[0] = texcoord[0];
2379 ret[1] = texcoord[1];
2383 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2385 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2386 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
2387 ret[0] = texcoord[0];
2388 ret[1] = texcoord[1];
2392 // float SPA_LIGHTMAP0_COLOR = 6;
2394 // ignore alpha for now..
2395 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2398 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2402 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2403 static void VM_SV_getsurfacenormal(void)
2406 msurface_t *surface;
2408 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal);
2409 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2410 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2412 // FIXME: implement rotation/scaling
2413 // note: this (incorrectly) assumes it is a simple polygon
2414 // note: this only returns the first triangle, so it doesn't work very
2415 // well for curved surfaces or arbitrary meshes
2416 TriangleNormal((model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex), (model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + 3, (model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + 6, normal);
2417 VectorNormalize(normal);
2418 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2420 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2421 static void VM_SV_getsurfacetexture(void)
2424 msurface_t *surface;
2425 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture);
2426 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2427 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2429 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2431 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2432 static void VM_SV_getsurfacenearpoint(void)
2434 int surfacenum, best;
2436 vec_t dist, bestdist;
2439 msurface_t *surface;
2441 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint);
2442 PRVM_G_FLOAT(OFS_RETURN) = -1;
2443 ed = PRVM_G_EDICT(OFS_PARM0);
2444 point = PRVM_G_VECTOR(OFS_PARM1);
2446 if (!ed || ed->priv.server->free)
2448 model = getmodel(ed);
2449 if (!model || !model->num_surfaces)
2452 // FIXME: implement rotation/scaling
2453 VectorSubtract(point, ed->fields.server->origin, p);
2455 bestdist = 1000000000;
2456 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2458 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2459 // first see if the nearest point on the surface's box is closer than the previous match
2460 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2461 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2462 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2463 dist = VectorLength2(clipped);
2464 if (dist < bestdist)
2466 // it is, check the nearest point on the actual geometry
2467 clippointtosurface(model, surface, p, clipped);
2468 VectorSubtract(clipped, p, clipped);
2469 dist += VectorLength2(clipped);
2470 if (dist < bestdist)
2472 // that's closer too, store it as the best match
2478 PRVM_G_FLOAT(OFS_RETURN) = best;
2480 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2481 static void VM_SV_getsurfaceclippedpoint(void)
2485 msurface_t *surface;
2487 VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint);
2488 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2489 ed = PRVM_G_EDICT(OFS_PARM0);
2490 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2492 // FIXME: implement rotation/scaling
2493 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2494 clippointtosurface(model, surface, p, out);
2495 // FIXME: implement rotation/scaling
2496 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2499 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2500 //this function originally written by KrimZon, made shorter by LordHavoc
2501 static void VM_SV_clientcommand (void)
2503 client_t *temp_client;
2505 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2507 //find client for this entity
2508 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2509 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2511 Con_Print("PF_clientcommand: entity is not a client\n");
2515 temp_client = host_client;
2516 host_client = svs.clients + i;
2517 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2518 host_client = temp_client;
2521 //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)
2522 static void VM_SV_setattachment (void)
2524 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2525 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2526 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2530 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2532 if (e == prog->edicts)
2534 VM_Warning("setattachment: can not modify world entity\n");
2537 if (e->priv.server->free)
2539 VM_Warning("setattachment: can not modify free entity\n");
2543 if (tagentity == NULL)
2544 tagentity = prog->edicts;
2546 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2548 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2550 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2553 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2555 modelindex = (int)tagentity->fields.server->modelindex;
2556 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2558 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2560 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);
2563 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));
2567 /////////////////////////////////////////
2568 // DP_MD3_TAGINFO extension coded by VorteX
2570 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2575 i = (int)e->fields.server->modelindex;
2576 if (i < 1 || i >= MAX_MODELS)
2578 model = sv.models[i];
2580 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2583 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2592 Matrix4x4_CreateIdentity(tag_localmatrix);
2595 && (modelindex = (int)e->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2596 && (model = sv.models[(int)e->fields.server->modelindex])
2597 && model->animscenes)
2599 frame = (int)e->fields.server->frame;
2600 if (frame < 0 || frame >= model->numframes)
2603 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)e->fields.server->skin, model->animscenes[frame].firstframe, tagindex - 1, parentindex, tagname, tag_localmatrix);
2614 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2623 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2624 if (val && val->_float != 0)
2625 scale = val->_float;
2628 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);
2633 ((modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[(int)ent->fields.server->modelindex]))
2635 model->type == mod_alias
2638 (((unsigned char)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.pflags)->_float) & PFLAGS_FULLDYNAMIC)
2640 ((gamemode == GAME_TENEBRAE) && ((unsigned int)ent->fields.server->effects & (16 | 32)))
2644 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);
2648 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2654 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2655 && (model = sv.models[(int)ent->fields.server->modelindex])
2656 && model->animscenes)
2658 // if model has wrong frame, engine automatically switches to model first frame
2659 frame = (int)ent->fields.server->frame;
2660 if (frame < 0 || frame >= model->numframes)
2662 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2664 *out = identitymatrix;
2668 // Warnings/errors code:
2669 // 0 - normal (everything all-right)
2672 // 3 - null or non-precached model
2673 // 4 - no tags with requested index
2674 // 5 - runaway loop at attachment chain
2675 extern cvar_t cl_bob;
2676 extern cvar_t cl_bobcycle;
2677 extern cvar_t cl_bobup;
2678 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2682 int modelindex, attachloop;
2683 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2686 *out = identitymatrix; // warnings and errors return identical matrix
2688 if (ent == prog->edicts)
2690 if (ent->priv.server->free)
2693 modelindex = (int)ent->fields.server->modelindex;
2694 if (modelindex <= 0 || modelindex > MAX_MODELS)
2697 model = sv.models[modelindex];
2699 tagmatrix = identitymatrix;
2700 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2704 if (attachloop >= 256) // prevent runaway looping
2706 // apply transformation by child's tagindex on parent entity and then
2707 // by parent entity itself
2708 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2709 if (ret && attachloop == 0)
2711 SV_GetEntityMatrix(ent, &entitymatrix, false);
2712 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2713 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2714 // next iteration we process the parent entity
2715 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2717 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2718 ent = PRVM_EDICT_NUM(val->edict);
2725 // RENDER_VIEWMODEL magic
2726 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2728 Matrix4x4_Copy(&tagmatrix, out);
2729 ent = PRVM_EDICT_NUM(val->edict);
2731 SV_GetEntityMatrix(ent, &entitymatrix, true);
2732 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2735 // Cl_bob, ported from rendering code
2736 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2739 // LordHavoc: this code is *weird*, but not replacable (I think it
2740 // should be done in QC on the server, but oh well, quake is quake)
2741 // LordHavoc: figured out bobup: the time at which the sin is at 180
2742 // degrees (which allows lengthening or squishing the peak or valley)
2743 cycle = sv.time/cl_bobcycle.value;
2744 cycle -= (int)cycle;
2745 if (cycle < cl_bobup.value)
2746 cycle = sin(M_PI * cycle / cl_bobup.value);
2748 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2749 // bob is proportional to velocity in the xy plane
2750 // (don't count Z, or jumping messes it up)
2751 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;
2752 bob = bob*0.3 + bob*0.7*cycle;
2753 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2760 //float(entity ent, string tagname) gettagindex;
2762 static void VM_SV_gettagindex (void)
2765 const char *tag_name;
2766 int modelindex, tag_index;
2768 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2770 ent = PRVM_G_EDICT(OFS_PARM0);
2771 tag_name = PRVM_G_STRING(OFS_PARM1);
2773 if (ent == prog->edicts)
2775 VM_Warning("gettagindex: can't affect world entity\n");
2778 if (ent->priv.server->free)
2780 VM_Warning("gettagindex: can't affect free entity\n");
2784 modelindex = (int)ent->fields.server->modelindex;
2786 if (modelindex <= 0 || modelindex > MAX_MODELS)
2787 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2790 tag_index = SV_GetTagIndex(ent, tag_name);
2792 if(developer.integer >= 100)
2793 Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2795 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2798 //vector(entity ent, float tagindex) gettaginfo;
2799 static void VM_SV_gettaginfo (void)
2803 matrix4x4_t tag_matrix;
2804 matrix4x4_t tag_localmatrix;
2806 const char *tagname;
2809 vec3_t fo, le, up, trans;
2811 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2813 e = PRVM_G_EDICT(OFS_PARM0);
2814 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2816 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2817 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, le, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2818 VectorScale(le, -1, prog->globals.server->v_right);
2819 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2820 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2822 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_parent)))
2823 val->_float = parentindex;
2824 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_name)))
2825 val->string = tagname ? PRVM_SetTempString(tagname) : 0;
2826 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_offset)))
2827 VectorCopy(trans, val->vector);
2828 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_forward)))
2829 VectorCopy(fo, val->vector);
2830 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_right)))
2831 VectorScale(le, -1, val->vector);
2832 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_up)))
2833 VectorCopy(up, val->vector);
2838 VM_Warning("gettagindex: can't affect world entity\n");
2841 VM_Warning("gettagindex: can't affect free entity\n");
2844 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2847 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2850 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2855 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2856 static void VM_SV_dropclient (void)
2859 client_t *oldhostclient;
2860 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2861 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2862 if (clientnum < 0 || clientnum >= svs.maxclients)
2864 VM_Warning("dropclient: not a client\n");
2867 if (!svs.clients[clientnum].active)
2869 VM_Warning("dropclient: that client slot is not connected\n");
2872 oldhostclient = host_client;
2873 host_client = svs.clients + clientnum;
2874 SV_DropClient(false);
2875 host_client = oldhostclient;
2878 //entity() spawnclient (DP_SV_BOTCLIENT)
2879 static void VM_SV_spawnclient (void)
2883 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2884 prog->xfunction->builtinsprofile += 2;
2886 for (i = 0;i < svs.maxclients;i++)
2888 if (!svs.clients[i].active)
2890 prog->xfunction->builtinsprofile += 100;
2891 SV_ConnectClient (i, NULL);
2892 // this has to be set or else ClientDisconnect won't be called
2893 // we assume the qc will call ClientConnect...
2894 svs.clients[i].clientconnectcalled = true;
2895 ed = PRVM_EDICT_NUM(i + 1);
2899 VM_RETURN_EDICT(ed);
2902 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2903 static void VM_SV_clienttype (void)
2906 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2907 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2908 if (clientnum < 0 || clientnum >= svs.maxclients)
2909 PRVM_G_FLOAT(OFS_RETURN) = 3;
2910 else if (!svs.clients[clientnum].active)
2911 PRVM_G_FLOAT(OFS_RETURN) = 0;
2912 else if (svs.clients[clientnum].netconnection)
2913 PRVM_G_FLOAT(OFS_RETURN) = 1;
2915 PRVM_G_FLOAT(OFS_RETURN) = 2;
2922 string(string key) serverkey
2925 void VM_SV_serverkey(void)
2927 char string[VM_STRINGTEMP_LENGTH];
2928 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2929 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2930 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2933 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2934 static void VM_SV_setmodelindex (void)
2939 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2941 e = PRVM_G_EDICT(OFS_PARM0);
2942 if (e == prog->edicts)
2944 VM_Warning("setmodelindex: can not modify world entity\n");
2947 if (e->priv.server->free)
2949 VM_Warning("setmodelindex: can not modify free entity\n");
2952 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2953 if (i <= 0 || i > MAX_MODELS)
2955 VM_Warning("setmodelindex: invalid modelindex\n");
2958 if (!sv.model_precache[i][0])
2960 VM_Warning("setmodelindex: model not precached\n");
2964 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2965 e->fields.server->modelindex = i;
2971 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2972 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2974 SetMinMaxSize (e, quakemins, quakemaxs, true);
2977 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2980 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2981 static void VM_SV_modelnameforindex (void)
2984 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2986 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2988 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2989 if (i <= 0 || i > MAX_MODELS)
2991 VM_Warning("modelnameforindex: invalid modelindex\n");
2994 if (!sv.model_precache[i][0])
2996 VM_Warning("modelnameforindex: model not precached\n");
3000 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
3003 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
3004 static void VM_SV_particleeffectnum (void)
3007 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
3008 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
3011 PRVM_G_FLOAT(OFS_RETURN) = i;
3014 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3015 static void VM_SV_trailparticles (void)
3017 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
3019 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3022 MSG_WriteByte(&sv.datagram, svc_trailparticles);
3023 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
3024 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
3025 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
3026 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
3027 SV_FlushBroadcastMessages();
3030 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
3031 static void VM_SV_pointparticles (void)
3033 int effectnum, count;
3035 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
3037 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3040 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
3041 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
3042 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
3043 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
3044 if (count == 1 && !VectorLength2(vel))
3047 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
3048 MSG_WriteShort(&sv.datagram, effectnum);
3049 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3053 // 1+2+12+12+2=29 bytes
3054 MSG_WriteByte(&sv.datagram, svc_pointparticles);
3055 MSG_WriteShort(&sv.datagram, effectnum);
3056 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3057 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
3058 MSG_WriteShort(&sv.datagram, count);
3061 SV_FlushBroadcastMessages();
3064 //PF_setpause, // void(float pause) setpause = #531;
3065 static void VM_SV_setpause(void) {
3067 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
3068 if (pauseValue != 0) { //pause the game
3070 sv.pausedstart = Sys_DoubleTime();
3071 } else { //disable pause, in case it was enabled
3072 if (sv.paused != 0) {
3077 // send notification to all clients
3078 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
3079 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
3082 prvm_builtin_t vm_sv_builtins[] = {
3083 NULL, // #0 NULL function (not callable) (QUAKE)
3084 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3085 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3086 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3087 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3088 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3089 VM_break, // #6 void() break (QUAKE)
3090 VM_random, // #7 float() random (QUAKE)
3091 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3092 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3093 VM_error, // #10 void(string e) error (QUAKE)
3094 VM_objerror, // #11 void(string e) objerror (QUAKE)
3095 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3096 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3097 VM_spawn, // #14 entity() spawn (QUAKE)
3098 VM_remove, // #15 void(entity e) remove (QUAKE)
3099 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3100 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3101 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3102 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3103 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3104 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3105 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3106 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3107 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3108 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3109 VM_ftos, // #26 string(float f) ftos (QUAKE)
3110 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3111 VM_coredump, // #28 void() coredump (QUAKE)
3112 VM_traceon, // #29 void() traceon (QUAKE)
3113 VM_traceoff, // #30 void() traceoff (QUAKE)
3114 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3115 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3116 NULL, // #33 (QUAKE)
3117 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3118 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3119 VM_rint, // #36 float(float v) rint (QUAKE)
3120 VM_floor, // #37 float(float v) floor (QUAKE)
3121 VM_ceil, // #38 float(float v) ceil (QUAKE)
3122 NULL, // #39 (QUAKE)
3123 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3124 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3125 NULL, // #42 (QUAKE)
3126 VM_fabs, // #43 float(float f) fabs (QUAKE)
3127 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3128 VM_cvar, // #45 float(string s) cvar (QUAKE)
3129 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3130 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3131 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3132 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3133 NULL, // #50 (QUAKE)
3134 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3135 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3136 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3137 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3138 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3139 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3140 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3141 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3142 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3143 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3144 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3145 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3146 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3147 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3148 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3149 NULL, // #66 (QUAKE)
3150 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3151 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3152 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3153 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3154 NULL, // #71 (QUAKE)
3155 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3156 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3157 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3158 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3159 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3160 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3161 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3162 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3163 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3164 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3165 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3166 NULL, // #83 (QUAKE)
3167 NULL, // #84 (QUAKE)
3168 NULL, // #85 (QUAKE)
3169 NULL, // #86 (QUAKE)
3170 NULL, // #87 (QUAKE)
3171 NULL, // #88 (QUAKE)
3172 NULL, // #89 (QUAKE)
3173 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3174 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3175 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3176 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3177 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3178 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3179 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3180 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3181 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3182 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3183 // FrikaC and Telejano range #100-#199
3194 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3195 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3196 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3197 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3198 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3199 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3200 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3201 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3202 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3203 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3284 // FTEQW range #200-#299
3303 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3306 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3307 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3308 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3309 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3310 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3311 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3312 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3313 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3314 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3315 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3317 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3325 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3385 // CSQC range #300-#399
3386 NULL, // #300 void() clearscene (EXT_CSQC)
3387 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3388 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3389 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3390 NULL, // #304 void() renderscene (EXT_CSQC)
3391 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3392 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3393 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3394 NULL, // #308 void() R_EndPolygon
3396 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3397 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3401 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3402 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3403 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3404 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3405 NULL, // #319 void(string name) freepic (EXT_CSQC)
3406 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3407 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3408 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3409 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3410 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3411 NULL, // #325 void(void) drawresetcliparea
3416 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3417 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3418 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3419 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3420 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3421 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3422 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3423 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3424 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3425 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3426 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3427 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3428 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3429 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3430 NULL, // #344 vector() getmousepos (EXT_CSQC)
3431 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3432 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3433 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3434 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3435 NULL, // #349 float() isdemo (EXT_CSQC)
3436 VM_isserver, // #350 float() isserver (EXT_CSQC)
3437 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3438 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3439 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3440 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3446 NULL, // #360 float() readbyte (EXT_CSQC)
3447 NULL, // #361 float() readchar (EXT_CSQC)
3448 NULL, // #362 float() readshort (EXT_CSQC)
3449 NULL, // #363 float() readlong (EXT_CSQC)
3450 NULL, // #364 float() readcoord (EXT_CSQC)
3451 NULL, // #365 float() readangle (EXT_CSQC)
3452 NULL, // #366 string() readstring (EXT_CSQC)
3453 NULL, // #367 float() readfloat (EXT_CSQC)
3486 // LordHavoc's range #400-#499
3487 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3488 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3489 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3490 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3491 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3492 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3493 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3494 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3495 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)
3496 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3497 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3498 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3499 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3500 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3501 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3502 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3503 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3504 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3505 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3506 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3507 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3508 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3509 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3510 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3511 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3512 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3513 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3514 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3515 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3516 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3517 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3518 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3519 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3520 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3521 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3522 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3523 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3524 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3525 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3526 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3527 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3528 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3529 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3530 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3531 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3532 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3533 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3534 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3535 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3536 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3537 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3538 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3539 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3540 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3541 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3542 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3543 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3544 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3546 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3547 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3548 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3549 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3550 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3551 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3552 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3553 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3554 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3555 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3556 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3558 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3559 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3560 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3561 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3562 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3563 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3564 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3565 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3566 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3567 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3568 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3569 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3570 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3571 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3572 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3573 VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3581 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3582 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3583 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3584 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3585 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3586 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3587 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3588 VM_SV_WritePicture, // #501
3590 VM_whichpack, // #503 string(string) whichpack = #503;
3597 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3598 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3599 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3600 VM_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET)
3601 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3602 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3603 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3604 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3605 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3606 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3618 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3711 VM_getextresponse, // #624 string getextresponse(void)
3715 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3717 void VM_SV_Cmd_Init(void)
3722 void VM_SV_Cmd_Reset(void)
3724 if(prog->funcoffsets.SV_Shutdown)
3726 func_t s = prog->funcoffsets.SV_Shutdown;
3727 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3728 PRVM_ExecuteProgram(s,"SV_Shutdown() required");