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 "
75 "DP_QC_FINDCHAIN_TOFIELD "
76 "DP_QC_FINDCHAINFLAGS "
77 "DP_QC_FINDCHAINFLOAT "
83 "DP_QC_GETSURFACEPOINTATTRIBUTE "
85 "DP_QC_GETTAGINFO_BONEPROPERTIES "
87 "DP_QC_GETTIME_CDTRACK "
89 "DP_QC_MULTIPLETEMPSTRINGS "
90 "DP_QC_NUM_FOR_EDICT "
92 "DP_QC_SINCOSSQRTPOW "
94 "DP_QC_STRINGBUFFERS "
95 "DP_QC_STRINGBUFFERS_CVARLIST "
96 "DP_QC_STRINGCOLORFUNCTIONS "
97 "DP_QC_STRING_CASE_FUNCTIONS "
99 "DP_QC_TOKENIZEBYSEPARATOR "
100 "DP_QC_TOKENIZE_CONSOLE "
103 "DP_QC_TRACE_MOVETYPE_HITMODEL "
104 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
105 "DP_QC_UNLIMITEDTEMPSTRINGS "
108 "DP_QC_VECTOANGLES_WITH_ROLL "
109 "DP_QC_VECTORVECTORS "
116 "DP_SND_DIRECTIONLESSATTNNONE "
123 "DP_SV_CLIENTCOLORS "
126 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
127 "DP_SV_DRAWONLYTOCLIENT "
130 "DP_SV_ENTITYCONTENTSTRANSITION "
131 "DP_SV_MODELFLAGS_AS_EFFECTS "
132 "DP_SV_MOVETYPESTEP_LANDEVENT "
134 "DP_SV_NODRAWTOCLIENT "
135 "DP_SV_ONENTITYNOSPAWNFUNCTION "
136 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
138 "DP_SV_PLAYERPHYSICS "
139 "DP_SV_POINTPARTICLES "
141 "DP_SV_PRECACHEANYTIME "
145 "DP_SV_ROTATINGBMODEL "
149 "DP_SV_SPAWNFUNC_PREFIX "
150 "DP_SV_WRITEPICTURE "
151 "DP_SV_WRITEUNTERMINATEDSTRING "
155 "DP_TE_EXPLOSIONRGB "
157 "DP_TE_PARTICLECUBE "
158 "DP_TE_PARTICLERAIN "
159 "DP_TE_PARTICLESNOW "
161 "DP_TE_QUADEFFECTS1 "
164 "DP_TE_STANDARDEFFECTBUILTINS "
165 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
171 "KRIMZON_SV_PARSECLIENTCOMMAND "
174 "NEXUIZ_PLAYERMODEL "
176 "PRYDON_CLIENTCURSOR "
177 "TENEBRAE_GFX_DLIGHTS "
180 //"EXT_CSQC " // not ready yet
187 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.
189 setorigin (entity, origin)
192 static void VM_SV_setorigin (void)
197 VM_SAFEPARMCOUNT(2, VM_setorigin);
199 e = PRVM_G_EDICT(OFS_PARM0);
200 if (e == prog->edicts)
202 VM_Warning("setorigin: can not modify world entity\n");
205 if (e->priv.server->free)
207 VM_Warning("setorigin: can not modify free entity\n");
210 org = PRVM_G_VECTOR(OFS_PARM1);
211 VectorCopy (org, e->fields.server->origin);
212 SV_LinkEdict (e, false);
215 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
216 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
220 for (i=0 ; i<3 ; i++)
222 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
224 // set derived values
225 VectorCopy (min, e->fields.server->mins);
226 VectorCopy (max, e->fields.server->maxs);
227 VectorSubtract (max, min, e->fields.server->size);
229 SV_LinkEdict (e, false);
236 the size box is rotated by the current angle
237 LordHavoc: no it isn't...
239 setsize (entity, minvector, maxvector)
242 static void VM_SV_setsize (void)
247 VM_SAFEPARMCOUNT(3, VM_setsize);
249 e = PRVM_G_EDICT(OFS_PARM0);
250 if (e == prog->edicts)
252 VM_Warning("setsize: can not modify world entity\n");
255 if (e->priv.server->free)
257 VM_Warning("setsize: can not modify free entity\n");
260 min = PRVM_G_VECTOR(OFS_PARM1);
261 max = PRVM_G_VECTOR(OFS_PARM2);
262 SetMinMaxSize (e, min, max, false);
270 setmodel(entity, model)
273 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
274 static void VM_SV_setmodel (void)
280 VM_SAFEPARMCOUNT(2, VM_setmodel);
282 e = PRVM_G_EDICT(OFS_PARM0);
283 if (e == prog->edicts)
285 VM_Warning("setmodel: can not modify world entity\n");
288 if (e->priv.server->free)
290 VM_Warning("setmodel: can not modify free entity\n");
293 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
294 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
295 e->fields.server->modelindex = i;
301 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
302 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
304 SetMinMaxSize (e, quakemins, quakemaxs, true);
307 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
314 single print to a specific client
316 sprint(clientent, value)
319 static void VM_SV_sprint (void)
323 char string[VM_STRINGTEMP_LENGTH];
325 VM_VarString(1, string, sizeof(string));
327 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
329 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
330 // LordHavoc: div0 requested that sprintto world operate like print
337 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
339 VM_Warning("tried to centerprint to a non-client\n");
343 client = svs.clients + entnum-1;
344 if (!client->netconnection)
347 MSG_WriteChar(&client->netconnection->message,svc_print);
348 MSG_WriteString(&client->netconnection->message, string);
356 single print to a specific client
358 centerprint(clientent, value)
361 static void VM_SV_centerprint (void)
365 char string[VM_STRINGTEMP_LENGTH];
367 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
369 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
371 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
373 VM_Warning("tried to centerprint to a non-client\n");
377 client = svs.clients + entnum-1;
378 if (!client->netconnection)
381 VM_VarString(1, string, sizeof(string));
382 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
383 MSG_WriteString(&client->netconnection->message, string);
390 particle(origin, color, count)
393 static void VM_SV_particle (void)
399 VM_SAFEPARMCOUNT(4, VM_SV_particle);
401 org = PRVM_G_VECTOR(OFS_PARM0);
402 dir = PRVM_G_VECTOR(OFS_PARM1);
403 color = PRVM_G_FLOAT(OFS_PARM2);
404 count = PRVM_G_FLOAT(OFS_PARM3);
405 SV_StartParticle (org, dir, (int)color, (int)count);
415 static void VM_SV_ambientsound (void)
419 float vol, attenuation;
422 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
424 pos = PRVM_G_VECTOR (OFS_PARM0);
425 samp = PRVM_G_STRING(OFS_PARM1);
426 vol = PRVM_G_FLOAT(OFS_PARM2);
427 attenuation = PRVM_G_FLOAT(OFS_PARM3);
429 // check to see if samp was properly precached
430 soundnum = SV_SoundIndex(samp, 1);
438 // add an svc_spawnambient command to the level signon packet
441 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
443 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
445 MSG_WriteVector(&sv.signon, pos, sv.protocol);
447 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
448 MSG_WriteShort (&sv.signon, soundnum);
450 MSG_WriteByte (&sv.signon, soundnum);
452 MSG_WriteByte (&sv.signon, (int)(vol*255));
453 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
461 Each entity can have eight independant sound sources, like voice,
464 Channel 0 is an auto-allocate channel, the others override anything
465 already running on that entity/channel pair.
467 An attenuation of 0 will play full volume everywhere in the level.
468 Larger attenuations will drop off.
472 static void VM_SV_sound (void)
476 prvm_edict_t *entity;
480 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
482 entity = PRVM_G_EDICT(OFS_PARM0);
483 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
484 sample = PRVM_G_STRING(OFS_PARM2);
485 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
486 attenuation = PRVM_G_FLOAT(OFS_PARM4);
489 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
493 if (volume < 0 || volume > 255)
495 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
499 if (attenuation < 0 || attenuation > 4)
501 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
505 if (channel < 0 || channel > 7)
507 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
511 SV_StartSound (entity, channel, sample, volume, attenuation);
518 Follows the same logic as VM_SV_sound, except instead of
519 an entity, an origin for the sound is provided, and channel
520 is omitted (since no entity is being tracked).
524 static void VM_SV_pointsound(void)
531 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
533 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
534 sample = PRVM_G_STRING(OFS_PARM1);
535 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
536 attenuation = PRVM_G_FLOAT(OFS_PARM3);
538 if (volume < 0 || volume > 255)
540 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
544 if (attenuation < 0 || attenuation > 4)
546 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
550 SV_StartPointSound (org, sample, volume, attenuation);
557 Used for use tracing and shot targeting
558 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
559 if the tryents flag is set.
561 traceline (vector1, vector2, movetype, ignore)
564 static void VM_SV_traceline (void)
571 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
573 prog->xfunction->builtinsprofile += 30;
575 v1 = PRVM_G_VECTOR(OFS_PARM0);
576 v2 = PRVM_G_VECTOR(OFS_PARM1);
577 move = (int)PRVM_G_FLOAT(OFS_PARM2);
578 ent = PRVM_G_EDICT(OFS_PARM3);
580 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]))
581 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));
583 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
585 VM_SetTraceGlobals(&trace);
593 Used for use tracing and shot targeting
594 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
595 if the tryents flag is set.
597 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
600 // LordHavoc: added this for my own use, VERY useful, similar to traceline
601 static void VM_SV_tracebox (void)
603 float *v1, *v2, *m1, *m2;
608 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
610 prog->xfunction->builtinsprofile += 30;
612 v1 = PRVM_G_VECTOR(OFS_PARM0);
613 m1 = PRVM_G_VECTOR(OFS_PARM1);
614 m2 = PRVM_G_VECTOR(OFS_PARM2);
615 v2 = PRVM_G_VECTOR(OFS_PARM3);
616 move = (int)PRVM_G_FLOAT(OFS_PARM4);
617 ent = PRVM_G_EDICT(OFS_PARM5);
619 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]))
620 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));
622 trace = SV_Move (v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
624 VM_SetTraceGlobals(&trace);
627 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
632 vec3_t original_origin;
633 vec3_t original_velocity;
634 vec3_t original_angles;
635 vec3_t original_avelocity;
639 VectorCopy(tossent->fields.server->origin , original_origin );
640 VectorCopy(tossent->fields.server->velocity , original_velocity );
641 VectorCopy(tossent->fields.server->angles , original_angles );
642 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
644 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
645 if (val != NULL && val->_float != 0)
646 gravity = val->_float;
649 gravity *= sv_gravity.value * 0.025;
651 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
653 SV_CheckVelocity (tossent);
654 tossent->fields.server->velocity[2] -= gravity;
655 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
656 VectorScale (tossent->fields.server->velocity, 0.05, move);
657 VectorAdd (tossent->fields.server->origin, move, end);
658 trace = SV_Move (tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
659 VectorCopy (trace.endpos, tossent->fields.server->origin);
660 tossent->fields.server->velocity[2] -= gravity;
662 if (trace.fraction < 1)
666 VectorCopy(original_origin , tossent->fields.server->origin );
667 VectorCopy(original_velocity , tossent->fields.server->velocity );
668 VectorCopy(original_angles , tossent->fields.server->angles );
669 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
674 static void VM_SV_tracetoss (void)
678 prvm_edict_t *ignore;
680 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
682 prog->xfunction->builtinsprofile += 600;
684 ent = PRVM_G_EDICT(OFS_PARM0);
685 if (ent == prog->edicts)
687 VM_Warning("tracetoss: can not use world entity\n");
690 ignore = PRVM_G_EDICT(OFS_PARM1);
692 trace = SV_Trace_Toss (ent, ignore);
694 VM_SetTraceGlobals(&trace);
697 //============================================================================
699 static int checkpvsbytes;
700 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
702 static int VM_SV_newcheckclient (int check)
708 // cycle to the next one
710 check = bound(1, check, svs.maxclients);
711 if (check == svs.maxclients)
719 prog->xfunction->builtinsprofile++;
721 if (i == svs.maxclients+1)
723 // look up the client's edict
724 ent = PRVM_EDICT_NUM(i);
725 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
726 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
728 // found a valid client (possibly the same one again)
732 // get the PVS for the entity
733 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
735 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
736 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
745 Returns a client (or object that has a client enemy) that would be a
748 If there is more than one valid option, they are cycled each frame
750 If (self.origin + self.viewofs) is not in the PVS of the current target,
751 it is not returned at all.
756 int c_invis, c_notvis;
757 static void VM_SV_checkclient (void)
759 prvm_edict_t *ent, *self;
762 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
764 // find a new check if on a new frame
765 if (sv.time - sv.lastchecktime >= 0.1)
767 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
768 sv.lastchecktime = sv.time;
771 // return check if it might be visible
772 ent = PRVM_EDICT_NUM(sv.lastcheck);
773 if (ent->priv.server->free || ent->fields.server->health <= 0)
775 VM_RETURN_EDICT(prog->edicts);
779 // if current entity can't possibly see the check entity, return 0
780 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
781 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
782 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
785 VM_RETURN_EDICT(prog->edicts);
789 // might be able to see it
791 VM_RETURN_EDICT(ent);
794 //============================================================================
800 Checks if an entity is in a point's PVS.
801 Should be fast but can be inexact.
803 float checkpvs(vector viewpos, entity viewee) = #240;
806 static void VM_SV_checkpvs (void)
809 prvm_edict_t *viewee;
813 static int fatpvsbytes;
814 static unsigned char fatpvs[MAX_MAP_LEAFS/8];
817 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
818 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
819 viewee = PRVM_G_EDICT(OFS_PARM1);
821 if(viewee->priv.server->free)
823 VM_Warning("checkpvs: can not check free entity\n");
824 PRVM_G_FLOAT(OFS_RETURN) = 4;
829 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
831 // no PVS support on this worldmodel... darn
832 PRVM_G_FLOAT(OFS_RETURN) = 3;
835 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
838 // viewpos isn't in any PVS... darn
839 PRVM_G_FLOAT(OFS_RETURN) = 2;
842 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
844 // using fat PVS like FTEQW does (slow)
845 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
847 // no PVS support on this worldmodel... darn
848 PRVM_G_FLOAT(OFS_RETURN) = 3;
851 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
854 // viewpos isn't in any PVS... darn
855 PRVM_G_FLOAT(OFS_RETURN) = 2;
858 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
867 Sends text over to the client's execution buffer
869 stuffcmd (clientent, value, ...)
872 static void VM_SV_stuffcmd (void)
876 char string[VM_STRINGTEMP_LENGTH];
878 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
880 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
881 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
883 VM_Warning("Can't stuffcmd to a non-client\n");
887 VM_VarString(1, string, sizeof(string));
890 host_client = svs.clients + entnum-1;
891 Host_ClientCommands ("%s", string);
899 Returns a chain of entities that have origins within a spherical area
901 findradius (origin, radius)
904 static void VM_SV_findradius (void)
906 prvm_edict_t *ent, *chain;
907 vec_t radius, radius2;
908 vec3_t org, eorg, mins, maxs;
911 prvm_edict_t *touchedicts[MAX_EDICTS];
914 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
917 chainfield = PRVM_G_INT(OFS_PARM2);
919 chainfield = prog->fieldoffsets.chain;
921 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
923 chain = (prvm_edict_t *)prog->edicts;
925 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
926 radius = PRVM_G_FLOAT(OFS_PARM1);
927 radius2 = radius * radius;
929 mins[0] = org[0] - (radius + 1);
930 mins[1] = org[1] - (radius + 1);
931 mins[2] = org[2] - (radius + 1);
932 maxs[0] = org[0] + (radius + 1);
933 maxs[1] = org[1] + (radius + 1);
934 maxs[2] = org[2] + (radius + 1);
935 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
936 if (numtouchedicts > MAX_EDICTS)
938 // this never happens
939 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
940 numtouchedicts = MAX_EDICTS;
942 for (i = 0;i < numtouchedicts;i++)
944 ent = touchedicts[i];
945 prog->xfunction->builtinsprofile++;
946 // Quake did not return non-solid entities but darkplaces does
947 // (note: this is the reason you can't blow up fallen zombies)
948 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
950 // LordHavoc: compare against bounding box rather than center so it
951 // doesn't miss large objects, and use DotProduct instead of Length
952 // for a major speedup
953 VectorSubtract(org, ent->fields.server->origin, eorg);
954 if (sv_gameplayfix_findradiusdistancetobox.integer)
956 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
957 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
958 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
961 VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
962 if (DotProduct(eorg, eorg) < radius2)
964 PRVM_EDICTFIELDVALUE(ent,chainfield)->edict = PRVM_EDICT_TO_PROG(chain);
969 VM_RETURN_EDICT(chain);
972 static void VM_SV_precache_sound (void)
974 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
975 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
978 static void VM_SV_precache_model (void)
980 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
981 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
982 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
989 float(float yaw, float dist[, settrace]) walkmove
992 static void VM_SV_walkmove (void)
1001 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1003 // assume failure if it returns early
1004 PRVM_G_FLOAT(OFS_RETURN) = 0;
1006 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1007 if (ent == prog->edicts)
1009 VM_Warning("walkmove: can not modify world entity\n");
1012 if (ent->priv.server->free)
1014 VM_Warning("walkmove: can not modify free entity\n");
1017 yaw = PRVM_G_FLOAT(OFS_PARM0);
1018 dist = PRVM_G_FLOAT(OFS_PARM1);
1019 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1021 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1024 yaw = yaw*M_PI*2 / 360;
1026 move[0] = cos(yaw)*dist;
1027 move[1] = sin(yaw)*dist;
1030 // save program state, because SV_movestep may call other progs
1031 oldf = prog->xfunction;
1032 oldself = prog->globals.server->self;
1034 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1037 // restore program state
1038 prog->xfunction = oldf;
1039 prog->globals.server->self = oldself;
1049 static void VM_SV_droptofloor (void)
1055 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1057 // assume failure if it returns early
1058 PRVM_G_FLOAT(OFS_RETURN) = 0;
1060 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1061 if (ent == prog->edicts)
1063 VM_Warning("droptofloor: can not modify world entity\n");
1066 if (ent->priv.server->free)
1068 VM_Warning("droptofloor: can not modify free entity\n");
1072 VectorCopy (ent->fields.server->origin, end);
1075 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1076 SV_UnstickEntity(ent);
1078 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1079 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1082 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]);
1083 VectorAdd(ent->fields.server->origin, offset, org);
1084 trace = SV_Move (org, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1085 VectorSubtract(trace.endpos, offset, trace.endpos);
1086 if (trace.startsolid)
1088 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]);
1089 SV_UnstickEntity(ent);
1090 SV_LinkEdict (ent, false);
1091 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1092 ent->fields.server->groundentity = 0;
1093 PRVM_G_FLOAT(OFS_RETURN) = 1;
1095 else if (trace.fraction < 1)
1097 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]);
1098 VectorCopy (trace.endpos, ent->fields.server->origin);
1099 SV_UnstickEntity(ent);
1100 SV_LinkEdict (ent, false);
1101 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1102 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1103 PRVM_G_FLOAT(OFS_RETURN) = 1;
1104 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1105 ent->priv.server->suspendedinairflag = true;
1110 if (trace.fraction != 1)
1112 if (trace.fraction < 1)
1113 VectorCopy (trace.endpos, ent->fields.server->origin);
1114 SV_LinkEdict (ent, false);
1115 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1116 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1117 PRVM_G_FLOAT(OFS_RETURN) = 1;
1118 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1119 ent->priv.server->suspendedinairflag = true;
1128 void(float style, string value) lightstyle
1131 static void VM_SV_lightstyle (void)
1138 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1140 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1141 val = PRVM_G_STRING(OFS_PARM1);
1143 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1144 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1147 // change the string in sv
1148 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1150 // send message to all clients on this server
1151 if (sv.state != ss_active)
1154 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1156 if (client->active && client->netconnection)
1158 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1159 MSG_WriteChar (&client->netconnection->message,style);
1160 MSG_WriteString (&client->netconnection->message, val);
1170 static void VM_SV_checkbottom (void)
1172 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1173 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1181 static void VM_SV_pointcontents (void)
1183 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1184 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1191 Pick a vector for the player to shoot along
1192 vector aim(entity, missilespeed)
1195 static void VM_SV_aim (void)
1197 prvm_edict_t *ent, *check, *bestent;
1198 vec3_t start, dir, end, bestdir;
1201 float dist, bestdist;
1204 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1206 // assume failure if it returns early
1207 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1208 // if sv_aim is so high it can't possibly accept anything, skip out early
1209 if (sv_aim.value >= 1)
1212 ent = PRVM_G_EDICT(OFS_PARM0);
1213 if (ent == prog->edicts)
1215 VM_Warning("aim: can not use world entity\n");
1218 if (ent->priv.server->free)
1220 VM_Warning("aim: can not use free entity\n");
1223 speed = PRVM_G_FLOAT(OFS_PARM1);
1225 VectorCopy (ent->fields.server->origin, start);
1228 // try sending a trace straight
1229 VectorCopy (prog->globals.server->v_forward, dir);
1230 VectorMA (start, 2048, dir, end);
1231 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1232 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1233 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1235 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1240 // try all possible entities
1241 VectorCopy (dir, bestdir);
1242 bestdist = sv_aim.value;
1245 check = PRVM_NEXT_EDICT(prog->edicts);
1246 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1248 prog->xfunction->builtinsprofile++;
1249 if (check->fields.server->takedamage != DAMAGE_AIM)
1253 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1254 continue; // don't aim at teammate
1255 for (j=0 ; j<3 ; j++)
1256 end[j] = check->fields.server->origin[j]
1257 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1258 VectorSubtract (end, start, dir);
1259 VectorNormalize (dir);
1260 dist = DotProduct (dir, prog->globals.server->v_forward);
1261 if (dist < bestdist)
1262 continue; // to far to turn
1263 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1264 if (tr.ent == check)
1265 { // can shoot at this one
1273 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1274 dist = DotProduct (dir, prog->globals.server->v_forward);
1275 VectorScale (prog->globals.server->v_forward, dist, end);
1277 VectorNormalize (end);
1278 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1282 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1287 ===============================================================================
1291 ===============================================================================
1294 #define MSG_BROADCAST 0 // unreliable to all
1295 #define MSG_ONE 1 // reliable to one (msg_entity)
1296 #define MSG_ALL 2 // reliable to all
1297 #define MSG_INIT 3 // write to the init string
1298 #define MSG_ENTITY 5
1300 sizebuf_t *WriteDest (void)
1306 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1310 return &sv.datagram;
1313 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1314 entnum = PRVM_NUM_FOR_EDICT(ent);
1315 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1317 VM_Warning ("WriteDest: tried to write to non-client\n");
1318 return &sv.reliable_datagram;
1321 return &svs.clients[entnum-1].netconnection->message;
1324 VM_Warning ("WriteDest: bad destination\n");
1326 return &sv.reliable_datagram;
1332 return sv.writeentitiestoclient_msg;
1338 static void VM_SV_WriteByte (void)
1340 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1341 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1344 static void VM_SV_WriteChar (void)
1346 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1347 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1350 static void VM_SV_WriteShort (void)
1352 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1353 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1356 static void VM_SV_WriteLong (void)
1358 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1359 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1362 static void VM_SV_WriteAngle (void)
1364 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1365 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1368 static void VM_SV_WriteCoord (void)
1370 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1371 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1374 static void VM_SV_WriteString (void)
1376 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1377 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1380 static void VM_SV_WriteUnterminatedString (void)
1382 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1383 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1387 static void VM_SV_WriteEntity (void)
1389 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1390 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1393 // writes a picture as at most size bytes of data
1395 // IMGNAME \0 SIZE(short) IMGDATA
1396 // if failed to read/compress:
1398 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1399 static void VM_SV_WritePicture (void)
1401 const char *imgname;
1405 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1407 imgname = PRVM_G_STRING(OFS_PARM1);
1408 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1412 MSG_WriteString(WriteDest(), imgname);
1413 if(Image_Compress(imgname, size, &buf, &size))
1416 MSG_WriteShort(WriteDest(), size);
1417 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1422 MSG_WriteShort(WriteDest(), 0);
1426 //////////////////////////////////////////////////////////
1428 static void VM_SV_makestatic (void)
1433 // allow 0 parameters due to an id1 qc bug in which this function is used
1434 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1435 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1437 if (prog->argc >= 1)
1438 ent = PRVM_G_EDICT(OFS_PARM0);
1440 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1441 if (ent == prog->edicts)
1443 VM_Warning("makestatic: can not modify world entity\n");
1446 if (ent->priv.server->free)
1448 VM_Warning("makestatic: can not modify free entity\n");
1453 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1458 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1459 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1460 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1462 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1464 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1465 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1466 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1470 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1471 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1472 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1475 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1476 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1477 for (i=0 ; i<3 ; i++)
1479 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1480 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1483 // throw the entity away now
1487 //=============================================================================
1494 static void VM_SV_setspawnparms (void)
1500 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1502 ent = PRVM_G_EDICT(OFS_PARM0);
1503 i = PRVM_NUM_FOR_EDICT(ent);
1504 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1506 Con_Print("tried to setspawnparms on a non-client\n");
1510 // copy spawn parms out of the client_t
1511 client = svs.clients + i-1;
1512 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1513 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1520 Returns a color vector indicating the lighting at the requested point.
1522 (Internal Operation note: actually measures the light beneath the point, just like
1523 the model lighting on the client)
1528 static void VM_SV_getlight (void)
1530 vec3_t ambientcolor, diffusecolor, diffusenormal;
1532 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1533 p = PRVM_G_VECTOR(OFS_PARM0);
1534 VectorClear(ambientcolor);
1535 VectorClear(diffusecolor);
1536 VectorClear(diffusenormal);
1537 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1538 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1539 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1544 unsigned char type; // 1/2/8 or other value if isn't used
1548 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1549 static int vm_customstats_last;
1551 void VM_CustomStats_Clear (void)
1555 Z_Free(vm_customstats);
1556 vm_customstats = NULL;
1557 vm_customstats_last = -1;
1561 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1569 for(i=0; i<vm_customstats_last+1 ;i++)
1571 if(!vm_customstats[i].type)
1573 switch(vm_customstats[i].type)
1575 //string as 16 bytes
1578 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1579 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1580 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1581 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1582 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1584 //float field sent as-is
1586 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1588 //integer value of float field
1590 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1598 // void(float index, float type, .void field) SV_AddStat = #232;
1599 // Set up an auto-sent player stat.
1600 // Client's get thier own fields sent to them. Index may not be less than 32.
1601 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1602 // 1: string (4 stats carrying a total of 16 charactures)
1603 // 2: float (one stat, float converted to an integer for transportation)
1604 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1605 static void VM_SV_AddStat (void)
1610 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1614 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1617 VM_Warning("PF_SV_AddStat: not enough memory\n");
1621 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1622 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1623 off = PRVM_G_INT (OFS_PARM2);
1628 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1631 if(i >= (MAX_CL_STATS-32))
1633 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1636 if(i > (MAX_CL_STATS-32-4) && type == 1)
1638 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1641 vm_customstats[i].type = type;
1642 vm_customstats[i].fieldoffset = off;
1643 if(vm_customstats_last < i)
1644 vm_customstats_last = i;
1651 copies data from one entity to another
1653 copyentity(src, dst)
1656 static void VM_SV_copyentity (void)
1658 prvm_edict_t *in, *out;
1659 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1660 in = PRVM_G_EDICT(OFS_PARM0);
1661 if (in == prog->edicts)
1663 VM_Warning("copyentity: can not read world entity\n");
1666 if (in->priv.server->free)
1668 VM_Warning("copyentity: can not read free entity\n");
1671 out = PRVM_G_EDICT(OFS_PARM1);
1672 if (out == prog->edicts)
1674 VM_Warning("copyentity: can not modify world entity\n");
1677 if (out->priv.server->free)
1679 VM_Warning("copyentity: can not modify free entity\n");
1682 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1683 SV_LinkEdict(out, false);
1691 sets the color of a client and broadcasts the update to all connected clients
1693 setcolor(clientent, value)
1696 static void VM_SV_setcolor (void)
1702 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1703 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1704 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1706 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1708 Con_Print("tried to setcolor a non-client\n");
1712 client = svs.clients + entnum-1;
1715 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1717 client->edict->fields.server->team = (i & 15) + 1;
1720 if (client->old_colors != client->colors)
1722 client->old_colors = client->colors;
1723 // send notification to all clients
1724 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1725 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1726 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1734 effect(origin, modelname, startframe, framecount, framerate)
1737 static void VM_SV_effect (void)
1741 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1742 s = PRVM_G_STRING(OFS_PARM1);
1745 VM_Warning("effect: no model specified\n");
1749 i = SV_ModelIndex(s, 1);
1752 VM_Warning("effect: model not precached\n");
1756 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1758 VM_Warning("effect: framecount < 1\n");
1762 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1764 VM_Warning("effect: framerate < 1\n");
1768 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));
1771 static void VM_SV_te_blood (void)
1773 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1774 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1776 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1777 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1779 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1780 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1781 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1783 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1784 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1785 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1787 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1788 SV_FlushBroadcastMessages();
1791 static void VM_SV_te_bloodshower (void)
1793 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1794 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1796 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1797 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1799 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1800 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1801 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1803 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1804 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1805 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1809 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1810 SV_FlushBroadcastMessages();
1813 static void VM_SV_te_explosionrgb (void)
1815 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1816 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1817 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1819 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1820 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1821 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1823 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1824 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1825 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1826 SV_FlushBroadcastMessages();
1829 static void VM_SV_te_particlecube (void)
1831 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1832 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1834 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1835 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1837 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1838 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1839 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1841 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1842 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1843 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1845 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1847 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1849 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1851 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1852 // gravity true/false
1853 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1855 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1856 SV_FlushBroadcastMessages();
1859 static void VM_SV_te_particlerain (void)
1861 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1862 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1864 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1865 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1868 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1869 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1873 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1875 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1876 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1877 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1879 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1881 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1882 SV_FlushBroadcastMessages();
1885 static void VM_SV_te_particlesnow (void)
1887 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1888 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1890 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1891 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1893 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1894 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1895 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1905 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1907 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1908 SV_FlushBroadcastMessages();
1911 static void VM_SV_te_spark (void)
1913 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1914 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1916 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1917 MSG_WriteByte(&sv.datagram, TE_SPARK);
1919 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1920 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1921 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1923 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1924 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1925 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1927 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1928 SV_FlushBroadcastMessages();
1931 static void VM_SV_te_gunshotquad (void)
1933 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1934 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1935 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1940 SV_FlushBroadcastMessages();
1943 static void VM_SV_te_spikequad (void)
1945 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1946 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1947 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1949 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1950 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1952 SV_FlushBroadcastMessages();
1955 static void VM_SV_te_superspikequad (void)
1957 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1958 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1959 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1964 SV_FlushBroadcastMessages();
1967 static void VM_SV_te_explosionquad (void)
1969 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
1970 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1971 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1973 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1974 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1975 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1976 SV_FlushBroadcastMessages();
1979 static void VM_SV_te_smallflash (void)
1981 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
1982 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1983 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1985 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1988 SV_FlushBroadcastMessages();
1991 static void VM_SV_te_customflash (void)
1993 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
1994 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1996 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1997 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1999 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2000 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2001 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2003 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2005 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2007 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2008 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2009 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2010 SV_FlushBroadcastMessages();
2013 static void VM_SV_te_gunshot (void)
2015 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2016 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2017 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2019 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2020 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2021 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2022 SV_FlushBroadcastMessages();
2025 static void VM_SV_te_spike (void)
2027 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2028 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2029 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2031 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2032 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2033 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2034 SV_FlushBroadcastMessages();
2037 static void VM_SV_te_superspike (void)
2039 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2040 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2041 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2043 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2044 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2045 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2046 SV_FlushBroadcastMessages();
2049 static void VM_SV_te_explosion (void)
2051 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2052 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2053 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2055 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2056 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2058 SV_FlushBroadcastMessages();
2061 static void VM_SV_te_tarexplosion (void)
2063 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2064 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2065 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2067 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2068 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2069 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2070 SV_FlushBroadcastMessages();
2073 static void VM_SV_te_wizspike (void)
2075 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2076 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2077 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2079 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2080 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2081 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2082 SV_FlushBroadcastMessages();
2085 static void VM_SV_te_knightspike (void)
2087 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2088 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2089 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2091 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2092 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2093 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2094 SV_FlushBroadcastMessages();
2097 static void VM_SV_te_lavasplash (void)
2099 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2100 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2101 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2103 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2104 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2105 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2106 SV_FlushBroadcastMessages();
2109 static void VM_SV_te_teleport (void)
2111 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2112 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2113 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2115 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2116 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2117 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2118 SV_FlushBroadcastMessages();
2121 static void VM_SV_te_explosion2 (void)
2123 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2124 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2125 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2127 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2128 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2129 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2131 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2132 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2133 SV_FlushBroadcastMessages();
2136 static void VM_SV_te_lightning1 (void)
2138 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2139 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2140 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2142 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2144 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2145 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2146 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2148 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2149 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2150 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2151 SV_FlushBroadcastMessages();
2154 static void VM_SV_te_lightning2 (void)
2156 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2157 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2158 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2160 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2162 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2163 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2164 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2166 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2167 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2168 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2169 SV_FlushBroadcastMessages();
2172 static void VM_SV_te_lightning3 (void)
2174 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2175 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2176 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2178 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2180 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2181 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2182 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2184 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2185 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2186 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2187 SV_FlushBroadcastMessages();
2190 static void VM_SV_te_beam (void)
2192 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2193 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2194 MSG_WriteByte(&sv.datagram, TE_BEAM);
2196 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2198 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2199 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2200 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2202 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2203 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2204 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2205 SV_FlushBroadcastMessages();
2208 static void VM_SV_te_plasmaburn (void)
2210 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2211 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2212 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2213 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2214 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2215 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2216 SV_FlushBroadcastMessages();
2219 static void VM_SV_te_flamejet (void)
2221 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2222 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2223 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2225 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2226 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2227 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2230 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2231 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2233 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2234 SV_FlushBroadcastMessages();
2237 void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2240 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2242 bestdist = 1000000000;
2244 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2246 // clip original point to each triangle of the surface and find the
2247 // triangle that is closest
2248 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2249 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2250 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2251 TriangleNormal(v[0], v[1], v[2], facenormal);
2252 VectorNormalize(facenormal);
2253 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2254 VectorMA(p, offsetdist, facenormal, temp);
2255 for (j = 0, k = 2;j < 3;k = j, j++)
2257 VectorSubtract(v[k], v[j], edgenormal);
2258 CrossProduct(edgenormal, facenormal, sidenormal);
2259 VectorNormalize(sidenormal);
2260 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2262 VectorMA(temp, offsetdist, sidenormal, temp);
2264 dist = VectorDistance2(temp, p);
2265 if (bestdist > dist)
2268 VectorCopy(temp, out);
2273 static dp_model_t *getmodel(prvm_edict_t *ed)
2276 if (!ed || ed->priv.server->free)
2278 modelindex = (int)ed->fields.server->modelindex;
2279 if (modelindex < 1 || modelindex >= MAX_MODELS)
2281 return sv.models[modelindex];
2284 static msurface_t *getsurface(dp_model_t *model, int surfacenum)
2286 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2288 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2292 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2293 static void VM_SV_getsurfacenumpoints(void)
2296 msurface_t *surface;
2297 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints);
2298 // return 0 if no such surface
2299 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2301 PRVM_G_FLOAT(OFS_RETURN) = 0;
2305 // note: this (incorrectly) assumes it is a simple polygon
2306 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2308 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2309 static void VM_SV_getsurfacepoint(void)
2313 msurface_t *surface;
2315 VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint);
2316 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2317 ed = PRVM_G_EDICT(OFS_PARM0);
2318 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2320 // note: this (incorrectly) assumes it is a simple polygon
2321 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2322 if (pointnum < 0 || pointnum >= surface->num_vertices)
2324 // FIXME: implement rotation/scaling
2325 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2327 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
2328 // float SPA_POSITION = 0;
2329 // float SPA_S_AXIS = 1;
2330 // float SPA_T_AXIS = 2;
2331 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2332 // float SPA_TEXCOORDS0 = 4;
2333 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2334 // float SPA_LIGHTMAP0_COLOR = 6;
2335 static void VM_SV_getsurfacepointattribute(void)
2339 msurface_t *surface;
2343 VM_SAFEPARMCOUNT(4, VM_SV_getsurfacepoint);
2344 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2345 ed = PRVM_G_EDICT(OFS_PARM0);
2346 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2348 // note: this (incorrectly) assumes it is a simple polygon
2349 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2350 if (pointnum < 0 || pointnum >= surface->num_vertices)
2352 // FIXME: implement rotation/scaling
2353 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
2355 switch( attributetype ) {
2356 // float SPA_POSITION = 0;
2358 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2360 // float SPA_S_AXIS = 1;
2362 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2364 // float SPA_T_AXIS = 2;
2366 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2368 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2370 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2372 // float SPA_TEXCOORDS0 = 4;
2374 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2375 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
2376 ret[0] = texcoord[0];
2377 ret[1] = texcoord[1];
2381 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2383 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2384 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
2385 ret[0] = texcoord[0];
2386 ret[1] = texcoord[1];
2390 // float SPA_LIGHTMAP0_COLOR = 6;
2392 // ignore alpha for now..
2393 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2396 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2400 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2401 static void VM_SV_getsurfacenormal(void)
2404 msurface_t *surface;
2406 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal);
2407 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2408 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2410 // FIXME: implement rotation/scaling
2411 // note: this (incorrectly) assumes it is a simple polygon
2412 // note: this only returns the first triangle, so it doesn't work very
2413 // well for curved surfaces or arbitrary meshes
2414 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);
2415 VectorNormalize(normal);
2416 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2418 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2419 static void VM_SV_getsurfacetexture(void)
2422 msurface_t *surface;
2423 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture);
2424 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2425 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2427 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2429 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2430 static void VM_SV_getsurfacenearpoint(void)
2432 int surfacenum, best;
2434 vec_t dist, bestdist;
2437 msurface_t *surface;
2439 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint);
2440 PRVM_G_FLOAT(OFS_RETURN) = -1;
2441 ed = PRVM_G_EDICT(OFS_PARM0);
2442 point = PRVM_G_VECTOR(OFS_PARM1);
2444 if (!ed || ed->priv.server->free)
2446 model = getmodel(ed);
2447 if (!model || !model->num_surfaces)
2450 // FIXME: implement rotation/scaling
2451 VectorSubtract(point, ed->fields.server->origin, p);
2453 bestdist = 1000000000;
2454 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2456 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2457 // first see if the nearest point on the surface's box is closer than the previous match
2458 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2459 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2460 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2461 dist = VectorLength2(clipped);
2462 if (dist < bestdist)
2464 // it is, check the nearest point on the actual geometry
2465 clippointtosurface(model, surface, p, clipped);
2466 VectorSubtract(clipped, p, clipped);
2467 dist += VectorLength2(clipped);
2468 if (dist < bestdist)
2470 // that's closer too, store it as the best match
2476 PRVM_G_FLOAT(OFS_RETURN) = best;
2478 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2479 static void VM_SV_getsurfaceclippedpoint(void)
2483 msurface_t *surface;
2485 VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint);
2486 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2487 ed = PRVM_G_EDICT(OFS_PARM0);
2488 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2490 // FIXME: implement rotation/scaling
2491 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2492 clippointtosurface(model, surface, p, out);
2493 // FIXME: implement rotation/scaling
2494 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2497 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2498 //this function originally written by KrimZon, made shorter by LordHavoc
2499 static void VM_SV_clientcommand (void)
2501 client_t *temp_client;
2503 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2505 //find client for this entity
2506 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2507 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2509 Con_Print("PF_clientcommand: entity is not a client\n");
2513 temp_client = host_client;
2514 host_client = svs.clients + i;
2515 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2516 host_client = temp_client;
2519 //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)
2520 static void VM_SV_setattachment (void)
2522 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2523 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2524 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2528 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2530 if (e == prog->edicts)
2532 VM_Warning("setattachment: can not modify world entity\n");
2535 if (e->priv.server->free)
2537 VM_Warning("setattachment: can not modify free entity\n");
2541 if (tagentity == NULL)
2542 tagentity = prog->edicts;
2544 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2546 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2548 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2551 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2553 modelindex = (int)tagentity->fields.server->modelindex;
2554 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2556 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2558 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);
2561 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));
2565 /////////////////////////////////////////
2566 // DP_MD3_TAGINFO extension coded by VorteX
2568 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2573 i = (int)e->fields.server->modelindex;
2574 if (i < 1 || i >= MAX_MODELS)
2576 model = sv.models[i];
2578 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2581 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2590 Matrix4x4_CreateIdentity(tag_localmatrix);
2593 && (modelindex = (int)e->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2594 && (model = sv.models[(int)e->fields.server->modelindex])
2595 && model->animscenes)
2597 frame = (int)e->fields.server->frame;
2598 if (frame < 0 || frame >= model->numframes)
2601 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)e->fields.server->skin, model->animscenes[frame].firstframe, tagindex - 1, parentindex, tagname, tag_localmatrix);
2612 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2621 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2622 if (val && val->_float != 0)
2623 scale = val->_float;
2626 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);
2631 ((modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[(int)ent->fields.server->modelindex]))
2633 model->type == mod_alias
2636 (((unsigned char)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.pflags)->_float) & PFLAGS_FULLDYNAMIC)
2638 ((gamemode == GAME_TENEBRAE) && ((unsigned int)ent->fields.server->effects & (16 | 32)))
2642 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);
2646 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2652 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2653 && (model = sv.models[(int)ent->fields.server->modelindex])
2654 && model->animscenes)
2656 // if model has wrong frame, engine automatically switches to model first frame
2657 frame = (int)ent->fields.server->frame;
2658 if (frame < 0 || frame >= model->numframes)
2660 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2662 *out = identitymatrix;
2666 // Warnings/errors code:
2667 // 0 - normal (everything all-right)
2670 // 3 - null or non-precached model
2671 // 4 - no tags with requested index
2672 // 5 - runaway loop at attachment chain
2673 extern cvar_t cl_bob;
2674 extern cvar_t cl_bobcycle;
2675 extern cvar_t cl_bobup;
2676 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2680 int modelindex, attachloop;
2681 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2684 *out = identitymatrix; // warnings and errors return identical matrix
2686 if (ent == prog->edicts)
2688 if (ent->priv.server->free)
2691 modelindex = (int)ent->fields.server->modelindex;
2692 if (modelindex <= 0 || modelindex > MAX_MODELS)
2695 model = sv.models[modelindex];
2697 tagmatrix = identitymatrix;
2698 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2702 if (attachloop >= 256) // prevent runaway looping
2704 // apply transformation by child's tagindex on parent entity and then
2705 // by parent entity itself
2706 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2707 if (ret && attachloop == 0)
2709 SV_GetEntityMatrix(ent, &entitymatrix, false);
2710 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2711 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2712 // next iteration we process the parent entity
2713 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2715 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2716 ent = PRVM_EDICT_NUM(val->edict);
2723 // RENDER_VIEWMODEL magic
2724 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2726 Matrix4x4_Copy(&tagmatrix, out);
2727 ent = PRVM_EDICT_NUM(val->edict);
2729 SV_GetEntityMatrix(ent, &entitymatrix, true);
2730 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2733 // Cl_bob, ported from rendering code
2734 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2737 // LordHavoc: this code is *weird*, but not replacable (I think it
2738 // should be done in QC on the server, but oh well, quake is quake)
2739 // LordHavoc: figured out bobup: the time at which the sin is at 180
2740 // degrees (which allows lengthening or squishing the peak or valley)
2741 cycle = sv.time/cl_bobcycle.value;
2742 cycle -= (int)cycle;
2743 if (cycle < cl_bobup.value)
2744 cycle = sin(M_PI * cycle / cl_bobup.value);
2746 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2747 // bob is proportional to velocity in the xy plane
2748 // (don't count Z, or jumping messes it up)
2749 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;
2750 bob = bob*0.3 + bob*0.7*cycle;
2751 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2758 //float(entity ent, string tagname) gettagindex;
2760 static void VM_SV_gettagindex (void)
2763 const char *tag_name;
2764 int modelindex, tag_index;
2766 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2768 ent = PRVM_G_EDICT(OFS_PARM0);
2769 tag_name = PRVM_G_STRING(OFS_PARM1);
2771 if (ent == prog->edicts)
2773 VM_Warning("gettagindex: can't affect world entity\n");
2776 if (ent->priv.server->free)
2778 VM_Warning("gettagindex: can't affect free entity\n");
2782 modelindex = (int)ent->fields.server->modelindex;
2784 if (modelindex <= 0 || modelindex > MAX_MODELS)
2785 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2788 tag_index = SV_GetTagIndex(ent, tag_name);
2790 if(developer.integer >= 100)
2791 Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2793 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2796 //vector(entity ent, float tagindex) gettaginfo;
2797 static void VM_SV_gettaginfo (void)
2801 matrix4x4_t tag_matrix;
2802 matrix4x4_t tag_localmatrix;
2804 const char *tagname;
2807 vec3_t fo, le, up, trans;
2809 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2811 e = PRVM_G_EDICT(OFS_PARM0);
2812 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2814 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2815 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, le, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2816 VectorScale(le, -1, prog->globals.server->v_right);
2817 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2818 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2820 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_parent)))
2821 val->_float = parentindex;
2822 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_name)))
2823 val->string = tagname ? PRVM_SetTempString(tagname) : 0;
2824 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_offset)))
2825 VectorCopy(trans, val->vector);
2826 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_forward)))
2827 VectorCopy(fo, val->vector);
2828 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_right)))
2829 VectorScale(le, -1, val->vector);
2830 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_up)))
2831 VectorCopy(up, val->vector);
2836 VM_Warning("gettagindex: can't affect world entity\n");
2839 VM_Warning("gettagindex: can't affect free entity\n");
2842 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2845 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2848 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2853 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2854 static void VM_SV_dropclient (void)
2857 client_t *oldhostclient;
2858 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2859 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2860 if (clientnum < 0 || clientnum >= svs.maxclients)
2862 VM_Warning("dropclient: not a client\n");
2865 if (!svs.clients[clientnum].active)
2867 VM_Warning("dropclient: that client slot is not connected\n");
2870 oldhostclient = host_client;
2871 host_client = svs.clients + clientnum;
2872 SV_DropClient(false);
2873 host_client = oldhostclient;
2876 //entity() spawnclient (DP_SV_BOTCLIENT)
2877 static void VM_SV_spawnclient (void)
2881 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2882 prog->xfunction->builtinsprofile += 2;
2884 for (i = 0;i < svs.maxclients;i++)
2886 if (!svs.clients[i].active)
2888 prog->xfunction->builtinsprofile += 100;
2889 SV_ConnectClient (i, NULL);
2890 // this has to be set or else ClientDisconnect won't be called
2891 // we assume the qc will call ClientConnect...
2892 svs.clients[i].clientconnectcalled = true;
2893 ed = PRVM_EDICT_NUM(i + 1);
2897 VM_RETURN_EDICT(ed);
2900 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2901 static void VM_SV_clienttype (void)
2904 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2905 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2906 if (clientnum < 0 || clientnum >= svs.maxclients)
2907 PRVM_G_FLOAT(OFS_RETURN) = 3;
2908 else if (!svs.clients[clientnum].active)
2909 PRVM_G_FLOAT(OFS_RETURN) = 0;
2910 else if (svs.clients[clientnum].netconnection)
2911 PRVM_G_FLOAT(OFS_RETURN) = 1;
2913 PRVM_G_FLOAT(OFS_RETURN) = 2;
2920 string(string key) serverkey
2923 void VM_SV_serverkey(void)
2925 char string[VM_STRINGTEMP_LENGTH];
2926 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2927 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2928 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2931 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2932 static void VM_SV_setmodelindex (void)
2937 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2939 e = PRVM_G_EDICT(OFS_PARM0);
2940 if (e == prog->edicts)
2942 VM_Warning("setmodelindex: can not modify world entity\n");
2945 if (e->priv.server->free)
2947 VM_Warning("setmodelindex: can not modify free entity\n");
2950 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2951 if (i <= 0 || i > MAX_MODELS)
2953 VM_Warning("setmodelindex: invalid modelindex\n");
2956 if (!sv.model_precache[i][0])
2958 VM_Warning("setmodelindex: model not precached\n");
2962 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2963 e->fields.server->modelindex = i;
2969 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2970 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2972 SetMinMaxSize (e, quakemins, quakemaxs, true);
2975 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2978 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2979 static void VM_SV_modelnameforindex (void)
2982 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2984 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2986 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2987 if (i <= 0 || i > MAX_MODELS)
2989 VM_Warning("modelnameforindex: invalid modelindex\n");
2992 if (!sv.model_precache[i][0])
2994 VM_Warning("modelnameforindex: model not precached\n");
2998 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
3001 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
3002 static void VM_SV_particleeffectnum (void)
3005 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
3006 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
3009 PRVM_G_FLOAT(OFS_RETURN) = i;
3012 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3013 static void VM_SV_trailparticles (void)
3015 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
3017 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3020 MSG_WriteByte(&sv.datagram, svc_trailparticles);
3021 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
3022 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
3023 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
3024 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
3025 SV_FlushBroadcastMessages();
3028 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
3029 static void VM_SV_pointparticles (void)
3031 int effectnum, count;
3033 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
3035 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3038 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
3039 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
3040 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
3041 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
3042 if (count == 1 && !VectorLength2(vel))
3045 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
3046 MSG_WriteShort(&sv.datagram, effectnum);
3047 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3051 // 1+2+12+12+2=29 bytes
3052 MSG_WriteByte(&sv.datagram, svc_pointparticles);
3053 MSG_WriteShort(&sv.datagram, effectnum);
3054 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3055 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
3056 MSG_WriteShort(&sv.datagram, count);
3059 SV_FlushBroadcastMessages();
3062 //PF_setpause, // void(float pause) setpause = #531;
3063 static void VM_SV_setpause(void) {
3065 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
3066 if (pauseValue != 0) { //pause the game
3068 sv.pausedstart = Sys_DoubleTime();
3069 } else { //disable pause, in case it was enabled
3070 if (sv.paused != 0) {
3075 // send notification to all clients
3076 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
3077 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
3080 prvm_builtin_t vm_sv_builtins[] = {
3081 NULL, // #0 NULL function (not callable) (QUAKE)
3082 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3083 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3084 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3085 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3086 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3087 VM_break, // #6 void() break (QUAKE)
3088 VM_random, // #7 float() random (QUAKE)
3089 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3090 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3091 VM_error, // #10 void(string e) error (QUAKE)
3092 VM_objerror, // #11 void(string e) objerror (QUAKE)
3093 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3094 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3095 VM_spawn, // #14 entity() spawn (QUAKE)
3096 VM_remove, // #15 void(entity e) remove (QUAKE)
3097 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3098 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3099 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3100 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3101 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3102 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3103 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3104 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3105 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3106 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3107 VM_ftos, // #26 string(float f) ftos (QUAKE)
3108 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3109 VM_coredump, // #28 void() coredump (QUAKE)
3110 VM_traceon, // #29 void() traceon (QUAKE)
3111 VM_traceoff, // #30 void() traceoff (QUAKE)
3112 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3113 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3114 NULL, // #33 (QUAKE)
3115 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3116 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3117 VM_rint, // #36 float(float v) rint (QUAKE)
3118 VM_floor, // #37 float(float v) floor (QUAKE)
3119 VM_ceil, // #38 float(float v) ceil (QUAKE)
3120 NULL, // #39 (QUAKE)
3121 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3122 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3123 NULL, // #42 (QUAKE)
3124 VM_fabs, // #43 float(float f) fabs (QUAKE)
3125 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3126 VM_cvar, // #45 float(string s) cvar (QUAKE)
3127 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3128 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3129 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3130 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3131 NULL, // #50 (QUAKE)
3132 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3133 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3134 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3135 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3136 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3137 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3138 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3139 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3140 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3141 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3142 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3143 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3144 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3145 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3146 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3147 NULL, // #66 (QUAKE)
3148 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3149 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3150 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3151 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3152 NULL, // #71 (QUAKE)
3153 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3154 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3155 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3156 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3157 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3158 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3159 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3160 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3161 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3162 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3163 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3164 NULL, // #83 (QUAKE)
3165 NULL, // #84 (QUAKE)
3166 NULL, // #85 (QUAKE)
3167 NULL, // #86 (QUAKE)
3168 NULL, // #87 (QUAKE)
3169 NULL, // #88 (QUAKE)
3170 NULL, // #89 (QUAKE)
3171 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3172 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3173 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3174 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3175 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3176 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3177 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3178 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3179 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3180 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3181 // FrikaC and Telejano range #100-#199
3192 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3193 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3194 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3195 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3196 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3197 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3198 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3199 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3200 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3201 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3282 // FTEQW range #200-#299
3301 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3304 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3305 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3306 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3307 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3308 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3309 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3310 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3311 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3312 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3313 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3315 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3323 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3383 // CSQC range #300-#399
3384 NULL, // #300 void() clearscene (EXT_CSQC)
3385 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3386 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3387 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3388 NULL, // #304 void() renderscene (EXT_CSQC)
3389 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3390 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3391 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3392 NULL, // #308 void() R_EndPolygon
3394 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3395 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3399 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3400 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3401 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3402 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3403 NULL, // #319 void(string name) freepic (EXT_CSQC)
3404 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3405 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3406 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3407 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3408 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3409 NULL, // #325 void(void) drawresetcliparea
3414 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3415 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3416 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3417 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3418 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3419 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3420 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3421 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3422 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3423 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3424 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3425 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3426 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3427 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3428 NULL, // #344 vector() getmousepos (EXT_CSQC)
3429 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3430 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3431 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3432 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3433 NULL, // #349 float() isdemo (EXT_CSQC)
3434 VM_isserver, // #350 float() isserver (EXT_CSQC)
3435 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3436 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3437 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3438 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3444 NULL, // #360 float() readbyte (EXT_CSQC)
3445 NULL, // #361 float() readchar (EXT_CSQC)
3446 NULL, // #362 float() readshort (EXT_CSQC)
3447 NULL, // #363 float() readlong (EXT_CSQC)
3448 NULL, // #364 float() readcoord (EXT_CSQC)
3449 NULL, // #365 float() readangle (EXT_CSQC)
3450 NULL, // #366 string() readstring (EXT_CSQC)
3451 NULL, // #367 float() readfloat (EXT_CSQC)
3484 // LordHavoc's range #400-#499
3485 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3486 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3487 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3488 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3489 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3490 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3491 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3492 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3493 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)
3494 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3495 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3496 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3497 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3498 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3499 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3500 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3501 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3502 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3503 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3504 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3505 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3506 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3507 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3508 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3509 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3510 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3511 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3512 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3513 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3514 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3515 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3516 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3517 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3518 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3519 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3520 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3521 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3522 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3523 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3524 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3525 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3526 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3527 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3528 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3529 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3530 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3531 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3532 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3533 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3534 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3535 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3536 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3537 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3538 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3539 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3540 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3541 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3542 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3544 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3545 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3546 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3547 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3548 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3549 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3550 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3551 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3552 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3553 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3554 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3556 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3557 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3558 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3559 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3560 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3561 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3562 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3563 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3564 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3565 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3566 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3567 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3568 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3569 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3570 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3571 VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3579 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3580 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3581 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3582 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3583 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3584 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3585 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3586 VM_SV_WritePicture, // #501
3588 VM_whichpack, // #503 string(string) whichpack = #503;
3595 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3596 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3597 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3598 VM_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET)
3599 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3600 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3601 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3602 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3603 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3604 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3616 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3620 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3622 void VM_SV_Cmd_Init(void)
3627 void VM_SV_Cmd_Reset(void)
3629 if(prog->funcoffsets.SV_Shutdown)
3631 func_t s = prog->funcoffsets.SV_Shutdown;
3632 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3633 PRVM_ExecuteProgram(s,"SV_Shutdown() required");