6 //============================================================================
11 char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
22 "DP_CSQC_MULTIFRAME_INTERPOLATION "
38 "DP_ENT_CUSTOMCOLORMAP "
39 "DP_ENT_EXTERIORMODELTOCLIENT "
42 "DP_ENT_LOWPRECISION "
46 "DP_GFX_EXTERNALTEXTURES "
47 "DP_GFX_EXTERNALTEXTURES_PERMAP "
49 "DP_GFX_QUAKE3MODELTAGS "
52 "DP_GFX_MODEL_INTERPOLATION "
54 "DP_HALFLIFE_MAP_CVAR "
60 "DP_MOVETYPEBOUNCEMISSILE "
63 "DP_QC_ASINACOSATANATAN2TAN "
68 "DP_QC_CVAR_DEFSTRING "
69 "DP_QC_CVAR_DESCRIPTION "
75 "DP_QC_EXTRESPONSEPACKET "
77 "DP_QC_FINDCHAIN_TOFIELD "
78 "DP_QC_FINDCHAINFLAGS "
79 "DP_QC_FINDCHAINFLOAT "
85 "DP_QC_GETSURFACEPOINTATTRIBUTE "
87 "DP_QC_GETTAGINFO_BONEPROPERTIES "
89 "DP_QC_GETTIME_CDTRACK "
91 "DP_QC_MULTIPLETEMPSTRINGS "
92 "DP_QC_NUM_FOR_EDICT "
94 "DP_QC_SINCOSSQRTPOW "
96 "DP_QC_STRINGBUFFERS "
97 "DP_QC_STRINGBUFFERS_CVARLIST "
98 "DP_QC_STRINGCOLORFUNCTIONS "
99 "DP_QC_STRING_CASE_FUNCTIONS "
101 "DP_QC_TOKENIZEBYSEPARATOR "
102 "DP_QC_TOKENIZE_CONSOLE "
105 "DP_QC_TRACE_MOVETYPE_HITMODEL "
106 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
107 "DP_QC_UNLIMITEDTEMPSTRINGS "
110 "DP_QC_VECTOANGLES_WITH_ROLL "
111 "DP_QC_VECTORVECTORS "
118 "DP_SND_DIRECTIONLESSATTNNONE "
125 "DP_SV_BOUNCEFACTOR "
126 "DP_SV_CLIENTCOLORS "
129 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
130 "DP_SV_DRAWONLYTOCLIENT "
133 "DP_SV_ENTITYCONTENTSTRANSITION "
134 "DP_SV_MODELFLAGS_AS_EFFECTS "
135 "DP_SV_MOVETYPESTEP_LANDEVENT "
137 "DP_SV_NODRAWTOCLIENT "
138 "DP_SV_ONENTITYNOSPAWNFUNCTION "
139 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
141 "DP_SV_PLAYERPHYSICS "
142 "DP_SV_POINTPARTICLES "
144 "DP_SV_PRECACHEANYTIME "
148 "DP_SV_ROTATINGBMODEL "
152 "DP_SV_SPAWNFUNC_PREFIX "
153 "DP_SV_WRITEPICTURE "
154 "DP_SV_WRITEUNTERMINATEDSTRING "
158 "DP_TE_EXPLOSIONRGB "
160 "DP_TE_PARTICLECUBE "
161 "DP_TE_PARTICLERAIN "
162 "DP_TE_PARTICLESNOW "
164 "DP_TE_QUADEFFECTS1 "
167 "DP_TE_STANDARDEFFECTBUILTINS "
168 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
174 "KRIMZON_SV_PARSECLIENTCOMMAND "
177 "NEXUIZ_PLAYERMODEL "
179 "PRYDON_CLIENTCURSOR "
180 "TENEBRAE_GFX_DLIGHTS "
183 "DP_CSQC_SPAWNPARTICLE "
184 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
185 "DP_CSQC_ENTITYNOCULL "
186 //"EXT_CSQC " // not ready yet
193 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.
195 setorigin (entity, origin)
198 static void VM_SV_setorigin (void)
203 VM_SAFEPARMCOUNT(2, VM_setorigin);
205 e = PRVM_G_EDICT(OFS_PARM0);
206 if (e == prog->edicts)
208 VM_Warning("setorigin: can not modify world entity\n");
211 if (e->priv.server->free)
213 VM_Warning("setorigin: can not modify free entity\n");
216 org = PRVM_G_VECTOR(OFS_PARM1);
217 VectorCopy (org, e->fields.server->origin);
221 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
222 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
226 for (i=0 ; i<3 ; i++)
228 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
230 // set derived values
231 VectorCopy (min, e->fields.server->mins);
232 VectorCopy (max, e->fields.server->maxs);
233 VectorSubtract (max, min, e->fields.server->size);
242 the size box is rotated by the current angle
243 LordHavoc: no it isn't...
245 setsize (entity, minvector, maxvector)
248 static void VM_SV_setsize (void)
253 VM_SAFEPARMCOUNT(3, VM_setsize);
255 e = PRVM_G_EDICT(OFS_PARM0);
256 if (e == prog->edicts)
258 VM_Warning("setsize: can not modify world entity\n");
261 if (e->priv.server->free)
263 VM_Warning("setsize: can not modify free entity\n");
266 min = PRVM_G_VECTOR(OFS_PARM1);
267 max = PRVM_G_VECTOR(OFS_PARM2);
268 SetMinMaxSize (e, min, max, false);
276 setmodel(entity, model)
279 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
280 static void VM_SV_setmodel (void)
286 VM_SAFEPARMCOUNT(2, VM_setmodel);
288 e = PRVM_G_EDICT(OFS_PARM0);
289 if (e == prog->edicts)
291 VM_Warning("setmodel: can not modify world entity\n");
294 if (e->priv.server->free)
296 VM_Warning("setmodel: can not modify free entity\n");
299 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
300 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
301 e->fields.server->modelindex = i;
307 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
308 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
310 SetMinMaxSize (e, quakemins, quakemaxs, true);
313 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
320 single print to a specific client
322 sprint(clientent, value)
325 static void VM_SV_sprint (void)
329 char string[VM_STRINGTEMP_LENGTH];
331 VM_VarString(1, string, sizeof(string));
333 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
335 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
336 // LordHavoc: div0 requested that sprintto world operate like print
343 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
345 VM_Warning("tried to centerprint to a non-client\n");
349 client = svs.clients + entnum-1;
350 if (!client->netconnection)
353 MSG_WriteChar(&client->netconnection->message,svc_print);
354 MSG_WriteString(&client->netconnection->message, string);
362 single print to a specific client
364 centerprint(clientent, value)
367 static void VM_SV_centerprint (void)
371 char string[VM_STRINGTEMP_LENGTH];
373 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
375 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
377 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
379 VM_Warning("tried to centerprint to a non-client\n");
383 client = svs.clients + entnum-1;
384 if (!client->netconnection)
387 VM_VarString(1, string, sizeof(string));
388 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
389 MSG_WriteString(&client->netconnection->message, string);
396 particle(origin, color, count)
399 static void VM_SV_particle (void)
405 VM_SAFEPARMCOUNT(4, VM_SV_particle);
407 org = PRVM_G_VECTOR(OFS_PARM0);
408 dir = PRVM_G_VECTOR(OFS_PARM1);
409 color = PRVM_G_FLOAT(OFS_PARM2);
410 count = PRVM_G_FLOAT(OFS_PARM3);
411 SV_StartParticle (org, dir, (int)color, (int)count);
421 static void VM_SV_ambientsound (void)
425 float vol, attenuation;
428 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
430 pos = PRVM_G_VECTOR (OFS_PARM0);
431 samp = PRVM_G_STRING(OFS_PARM1);
432 vol = PRVM_G_FLOAT(OFS_PARM2);
433 attenuation = PRVM_G_FLOAT(OFS_PARM3);
435 // check to see if samp was properly precached
436 soundnum = SV_SoundIndex(samp, 1);
444 // add an svc_spawnambient command to the level signon packet
447 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
449 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
451 MSG_WriteVector(&sv.signon, pos, sv.protocol);
453 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
454 MSG_WriteShort (&sv.signon, soundnum);
456 MSG_WriteByte (&sv.signon, soundnum);
458 MSG_WriteByte (&sv.signon, (int)(vol*255));
459 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
467 Each entity can have eight independant sound sources, like voice,
470 Channel 0 is an auto-allocate channel, the others override anything
471 already running on that entity/channel pair.
473 An attenuation of 0 will play full volume everywhere in the level.
474 Larger attenuations will drop off.
478 static void VM_SV_sound (void)
482 prvm_edict_t *entity;
486 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
488 entity = PRVM_G_EDICT(OFS_PARM0);
489 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
490 sample = PRVM_G_STRING(OFS_PARM2);
491 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
492 attenuation = PRVM_G_FLOAT(OFS_PARM4);
495 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
499 if (volume < 0 || volume > 255)
501 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
505 if (attenuation < 0 || attenuation > 4)
507 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
511 if (channel < 0 || channel > 7)
513 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
517 SV_StartSound (entity, channel, sample, volume, attenuation);
524 Follows the same logic as VM_SV_sound, except instead of
525 an entity, an origin for the sound is provided, and channel
526 is omitted (since no entity is being tracked).
530 static void VM_SV_pointsound(void)
537 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
539 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
540 sample = PRVM_G_STRING(OFS_PARM1);
541 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
542 attenuation = PRVM_G_FLOAT(OFS_PARM3);
544 if (volume < 0 || volume > 255)
546 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
550 if (attenuation < 0 || attenuation > 4)
552 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
556 SV_StartPointSound (org, sample, volume, attenuation);
563 Used for use tracing and shot targeting
564 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
565 if the tryents flag is set.
567 traceline (vector1, vector2, movetype, ignore)
570 static void VM_SV_traceline (void)
577 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
579 prog->xfunction->builtinsprofile += 30;
581 v1 = PRVM_G_VECTOR(OFS_PARM0);
582 v2 = PRVM_G_VECTOR(OFS_PARM1);
583 move = (int)PRVM_G_FLOAT(OFS_PARM2);
584 ent = PRVM_G_EDICT(OFS_PARM3);
586 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]))
587 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));
589 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
591 VM_SetTraceGlobals(&trace);
599 Used for use tracing and shot targeting
600 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
601 if the tryents flag is set.
603 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
606 // LordHavoc: added this for my own use, VERY useful, similar to traceline
607 static void VM_SV_tracebox (void)
609 float *v1, *v2, *m1, *m2;
614 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
616 prog->xfunction->builtinsprofile += 30;
618 v1 = PRVM_G_VECTOR(OFS_PARM0);
619 m1 = PRVM_G_VECTOR(OFS_PARM1);
620 m2 = PRVM_G_VECTOR(OFS_PARM2);
621 v2 = PRVM_G_VECTOR(OFS_PARM3);
622 move = (int)PRVM_G_FLOAT(OFS_PARM4);
623 ent = PRVM_G_EDICT(OFS_PARM5);
625 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]))
626 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));
628 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
630 VM_SetTraceGlobals(&trace);
633 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
638 vec3_t original_origin;
639 vec3_t original_velocity;
640 vec3_t original_angles;
641 vec3_t original_avelocity;
645 VectorCopy(tossent->fields.server->origin , original_origin );
646 VectorCopy(tossent->fields.server->velocity , original_velocity );
647 VectorCopy(tossent->fields.server->angles , original_angles );
648 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
650 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
651 if (val != NULL && val->_float != 0)
652 gravity = val->_float;
655 gravity *= sv_gravity.value * 0.025;
657 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
659 SV_CheckVelocity (tossent);
660 tossent->fields.server->velocity[2] -= gravity;
661 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
662 VectorScale (tossent->fields.server->velocity, 0.05, move);
663 VectorAdd (tossent->fields.server->origin, move, end);
664 trace = SV_TraceBox(tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
665 VectorCopy (trace.endpos, tossent->fields.server->origin);
666 tossent->fields.server->velocity[2] -= gravity;
668 if (trace.fraction < 1)
672 VectorCopy(original_origin , tossent->fields.server->origin );
673 VectorCopy(original_velocity , tossent->fields.server->velocity );
674 VectorCopy(original_angles , tossent->fields.server->angles );
675 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
680 static void VM_SV_tracetoss (void)
684 prvm_edict_t *ignore;
686 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
688 prog->xfunction->builtinsprofile += 600;
690 ent = PRVM_G_EDICT(OFS_PARM0);
691 if (ent == prog->edicts)
693 VM_Warning("tracetoss: can not use world entity\n");
696 ignore = PRVM_G_EDICT(OFS_PARM1);
698 trace = SV_Trace_Toss (ent, ignore);
700 VM_SetTraceGlobals(&trace);
703 //============================================================================
705 static int checkpvsbytes;
706 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
708 static int VM_SV_newcheckclient (int check)
714 // cycle to the next one
716 check = bound(1, check, svs.maxclients);
717 if (check == svs.maxclients)
725 prog->xfunction->builtinsprofile++;
727 if (i == svs.maxclients+1)
729 // look up the client's edict
730 ent = PRVM_EDICT_NUM(i);
731 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
732 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
734 // found a valid client (possibly the same one again)
738 // get the PVS for the entity
739 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
741 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
742 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
751 Returns a client (or object that has a client enemy) that would be a
754 If there is more than one valid option, they are cycled each frame
756 If (self.origin + self.viewofs) is not in the PVS of the current target,
757 it is not returned at all.
762 int c_invis, c_notvis;
763 static void VM_SV_checkclient (void)
765 prvm_edict_t *ent, *self;
768 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
770 // find a new check if on a new frame
771 if (sv.time - sv.lastchecktime >= 0.1)
773 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
774 sv.lastchecktime = sv.time;
777 // return check if it might be visible
778 ent = PRVM_EDICT_NUM(sv.lastcheck);
779 if (ent->priv.server->free || ent->fields.server->health <= 0)
781 VM_RETURN_EDICT(prog->edicts);
785 // if current entity can't possibly see the check entity, return 0
786 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
787 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
788 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
791 VM_RETURN_EDICT(prog->edicts);
795 // might be able to see it
797 VM_RETURN_EDICT(ent);
800 //============================================================================
806 Checks if an entity is in a point's PVS.
807 Should be fast but can be inexact.
809 float checkpvs(vector viewpos, entity viewee) = #240;
812 static void VM_SV_checkpvs (void)
815 prvm_edict_t *viewee;
819 static int fatpvsbytes;
820 static unsigned char fatpvs[MAX_MAP_LEAFS/8];
823 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
824 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
825 viewee = PRVM_G_EDICT(OFS_PARM1);
827 if(viewee->priv.server->free)
829 VM_Warning("checkpvs: can not check free entity\n");
830 PRVM_G_FLOAT(OFS_RETURN) = 4;
835 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
837 // no PVS support on this worldmodel... darn
838 PRVM_G_FLOAT(OFS_RETURN) = 3;
841 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
844 // viewpos isn't in any PVS... darn
845 PRVM_G_FLOAT(OFS_RETURN) = 2;
848 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
850 // using fat PVS like FTEQW does (slow)
851 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
853 // no PVS support on this worldmodel... darn
854 PRVM_G_FLOAT(OFS_RETURN) = 3;
857 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
860 // viewpos isn't in any PVS... darn
861 PRVM_G_FLOAT(OFS_RETURN) = 2;
864 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
873 Sends text over to the client's execution buffer
875 stuffcmd (clientent, value, ...)
878 static void VM_SV_stuffcmd (void)
882 char string[VM_STRINGTEMP_LENGTH];
884 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
886 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
887 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
889 VM_Warning("Can't stuffcmd to a non-client\n");
893 VM_VarString(1, string, sizeof(string));
896 host_client = svs.clients + entnum-1;
897 Host_ClientCommands ("%s", string);
905 Returns a chain of entities that have origins within a spherical area
907 findradius (origin, radius)
910 static void VM_SV_findradius (void)
912 prvm_edict_t *ent, *chain;
913 vec_t radius, radius2;
914 vec3_t org, eorg, mins, maxs;
917 prvm_edict_t *touchedicts[MAX_EDICTS];
920 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
923 chainfield = PRVM_G_INT(OFS_PARM2);
925 chainfield = prog->fieldoffsets.chain;
927 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
929 chain = (prvm_edict_t *)prog->edicts;
931 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
932 radius = PRVM_G_FLOAT(OFS_PARM1);
933 radius2 = radius * radius;
935 mins[0] = org[0] - (radius + 1);
936 mins[1] = org[1] - (radius + 1);
937 mins[2] = org[2] - (radius + 1);
938 maxs[0] = org[0] + (radius + 1);
939 maxs[1] = org[1] + (radius + 1);
940 maxs[2] = org[2] + (radius + 1);
941 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
942 if (numtouchedicts > MAX_EDICTS)
944 // this never happens
945 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
946 numtouchedicts = MAX_EDICTS;
948 for (i = 0;i < numtouchedicts;i++)
950 ent = touchedicts[i];
951 prog->xfunction->builtinsprofile++;
952 // Quake did not return non-solid entities but darkplaces does
953 // (note: this is the reason you can't blow up fallen zombies)
954 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
956 // LordHavoc: compare against bounding box rather than center so it
957 // doesn't miss large objects, and use DotProduct instead of Length
958 // for a major speedup
959 VectorSubtract(org, ent->fields.server->origin, eorg);
960 if (sv_gameplayfix_findradiusdistancetobox.integer)
962 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
963 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
964 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
967 VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
968 if (DotProduct(eorg, eorg) < radius2)
970 PRVM_EDICTFIELDVALUE(ent,chainfield)->edict = PRVM_EDICT_TO_PROG(chain);
975 VM_RETURN_EDICT(chain);
978 static void VM_SV_precache_sound (void)
980 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
981 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
984 static void VM_SV_precache_model (void)
986 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
987 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
988 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
995 float(float yaw, float dist[, settrace]) walkmove
998 static void VM_SV_walkmove (void)
1007 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1009 // assume failure if it returns early
1010 PRVM_G_FLOAT(OFS_RETURN) = 0;
1012 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1013 if (ent == prog->edicts)
1015 VM_Warning("walkmove: can not modify world entity\n");
1018 if (ent->priv.server->free)
1020 VM_Warning("walkmove: can not modify free entity\n");
1023 yaw = PRVM_G_FLOAT(OFS_PARM0);
1024 dist = PRVM_G_FLOAT(OFS_PARM1);
1025 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1027 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1030 yaw = yaw*M_PI*2 / 360;
1032 move[0] = cos(yaw)*dist;
1033 move[1] = sin(yaw)*dist;
1036 // save program state, because SV_movestep may call other progs
1037 oldf = prog->xfunction;
1038 oldself = prog->globals.server->self;
1040 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1043 // restore program state
1044 prog->xfunction = oldf;
1045 prog->globals.server->self = oldself;
1055 static void VM_SV_droptofloor (void)
1061 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1063 // assume failure if it returns early
1064 PRVM_G_FLOAT(OFS_RETURN) = 0;
1066 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1067 if (ent == prog->edicts)
1069 VM_Warning("droptofloor: can not modify world entity\n");
1072 if (ent->priv.server->free)
1074 VM_Warning("droptofloor: can not modify free entity\n");
1078 VectorCopy (ent->fields.server->origin, end);
1081 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1082 SV_UnstickEntity(ent);
1084 trace = SV_TraceBox(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1085 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1088 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]);
1089 VectorAdd(ent->fields.server->origin, offset, org);
1090 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1091 VectorSubtract(trace.endpos, offset, trace.endpos);
1092 if (trace.startsolid)
1094 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]);
1095 SV_UnstickEntity(ent);
1097 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1098 ent->fields.server->groundentity = 0;
1099 PRVM_G_FLOAT(OFS_RETURN) = 1;
1101 else if (trace.fraction < 1)
1103 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]);
1104 VectorCopy (trace.endpos, ent->fields.server->origin);
1105 SV_UnstickEntity(ent);
1107 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1108 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1109 PRVM_G_FLOAT(OFS_RETURN) = 1;
1110 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1111 ent->priv.server->suspendedinairflag = true;
1116 if (trace.fraction != 1)
1118 if (trace.fraction < 1)
1119 VectorCopy (trace.endpos, ent->fields.server->origin);
1121 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1122 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1123 PRVM_G_FLOAT(OFS_RETURN) = 1;
1124 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1125 ent->priv.server->suspendedinairflag = true;
1134 void(float style, string value) lightstyle
1137 static void VM_SV_lightstyle (void)
1144 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1146 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1147 val = PRVM_G_STRING(OFS_PARM1);
1149 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1150 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1153 // change the string in sv
1154 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1156 // send message to all clients on this server
1157 if (sv.state != ss_active)
1160 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1162 if (client->active && client->netconnection)
1164 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1165 MSG_WriteChar (&client->netconnection->message,style);
1166 MSG_WriteString (&client->netconnection->message, val);
1176 static void VM_SV_checkbottom (void)
1178 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1179 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1187 static void VM_SV_pointcontents (void)
1189 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1190 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1197 Pick a vector for the player to shoot along
1198 vector aim(entity, missilespeed)
1201 static void VM_SV_aim (void)
1203 prvm_edict_t *ent, *check, *bestent;
1204 vec3_t start, dir, end, bestdir;
1207 float dist, bestdist;
1210 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1212 // assume failure if it returns early
1213 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1214 // if sv_aim is so high it can't possibly accept anything, skip out early
1215 if (sv_aim.value >= 1)
1218 ent = PRVM_G_EDICT(OFS_PARM0);
1219 if (ent == prog->edicts)
1221 VM_Warning("aim: can not use world entity\n");
1224 if (ent->priv.server->free)
1226 VM_Warning("aim: can not use free entity\n");
1229 speed = PRVM_G_FLOAT(OFS_PARM1);
1231 VectorCopy (ent->fields.server->origin, start);
1234 // try sending a trace straight
1235 VectorCopy (prog->globals.server->v_forward, dir);
1236 VectorMA (start, 2048, dir, end);
1237 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1238 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1239 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1241 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1246 // try all possible entities
1247 VectorCopy (dir, bestdir);
1248 bestdist = sv_aim.value;
1251 check = PRVM_NEXT_EDICT(prog->edicts);
1252 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1254 prog->xfunction->builtinsprofile++;
1255 if (check->fields.server->takedamage != DAMAGE_AIM)
1259 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1260 continue; // don't aim at teammate
1261 for (j=0 ; j<3 ; j++)
1262 end[j] = check->fields.server->origin[j]
1263 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1264 VectorSubtract (end, start, dir);
1265 VectorNormalize (dir);
1266 dist = DotProduct (dir, prog->globals.server->v_forward);
1267 if (dist < bestdist)
1268 continue; // to far to turn
1269 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1270 if (tr.ent == check)
1271 { // can shoot at this one
1279 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1280 dist = DotProduct (dir, prog->globals.server->v_forward);
1281 VectorScale (prog->globals.server->v_forward, dist, end);
1283 VectorNormalize (end);
1284 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1288 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1293 ===============================================================================
1297 ===============================================================================
1300 #define MSG_BROADCAST 0 // unreliable to all
1301 #define MSG_ONE 1 // reliable to one (msg_entity)
1302 #define MSG_ALL 2 // reliable to all
1303 #define MSG_INIT 3 // write to the init string
1304 #define MSG_ENTITY 5
1306 sizebuf_t *WriteDest (void)
1312 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1316 return &sv.datagram;
1319 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1320 entnum = PRVM_NUM_FOR_EDICT(ent);
1321 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1323 VM_Warning ("WriteDest: tried to write to non-client\n");
1324 return &sv.reliable_datagram;
1327 return &svs.clients[entnum-1].netconnection->message;
1330 VM_Warning ("WriteDest: bad destination\n");
1332 return &sv.reliable_datagram;
1338 return sv.writeentitiestoclient_msg;
1344 static void VM_SV_WriteByte (void)
1346 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1347 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1350 static void VM_SV_WriteChar (void)
1352 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1353 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1356 static void VM_SV_WriteShort (void)
1358 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1359 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1362 static void VM_SV_WriteLong (void)
1364 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1365 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1368 static void VM_SV_WriteAngle (void)
1370 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1371 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1374 static void VM_SV_WriteCoord (void)
1376 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1377 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1380 static void VM_SV_WriteString (void)
1382 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1383 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1386 static void VM_SV_WriteUnterminatedString (void)
1388 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1389 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1393 static void VM_SV_WriteEntity (void)
1395 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1396 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1399 // writes a picture as at most size bytes of data
1401 // IMGNAME \0 SIZE(short) IMGDATA
1402 // if failed to read/compress:
1404 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1405 static void VM_SV_WritePicture (void)
1407 const char *imgname;
1411 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1413 imgname = PRVM_G_STRING(OFS_PARM1);
1414 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1418 MSG_WriteString(WriteDest(), imgname);
1419 if(Image_Compress(imgname, size, &buf, &size))
1422 MSG_WriteShort(WriteDest(), size);
1423 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1428 MSG_WriteShort(WriteDest(), 0);
1432 //////////////////////////////////////////////////////////
1434 static void VM_SV_makestatic (void)
1439 // allow 0 parameters due to an id1 qc bug in which this function is used
1440 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1441 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1443 if (prog->argc >= 1)
1444 ent = PRVM_G_EDICT(OFS_PARM0);
1446 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1447 if (ent == prog->edicts)
1449 VM_Warning("makestatic: can not modify world entity\n");
1452 if (ent->priv.server->free)
1454 VM_Warning("makestatic: can not modify free entity\n");
1459 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1464 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1465 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1466 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1468 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1470 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1471 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1472 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1476 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1477 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1478 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1481 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1482 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1483 for (i=0 ; i<3 ; i++)
1485 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1486 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1489 // throw the entity away now
1493 //=============================================================================
1500 static void VM_SV_setspawnparms (void)
1506 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1508 ent = PRVM_G_EDICT(OFS_PARM0);
1509 i = PRVM_NUM_FOR_EDICT(ent);
1510 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1512 Con_Print("tried to setspawnparms on a non-client\n");
1516 // copy spawn parms out of the client_t
1517 client = svs.clients + i-1;
1518 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1519 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1526 Returns a color vector indicating the lighting at the requested point.
1528 (Internal Operation note: actually measures the light beneath the point, just like
1529 the model lighting on the client)
1534 static void VM_SV_getlight (void)
1536 vec3_t ambientcolor, diffusecolor, diffusenormal;
1538 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1539 p = PRVM_G_VECTOR(OFS_PARM0);
1540 VectorClear(ambientcolor);
1541 VectorClear(diffusecolor);
1542 VectorClear(diffusenormal);
1543 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1544 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1545 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1550 unsigned char type; // 1/2/8 or other value if isn't used
1554 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1555 static int vm_customstats_last;
1557 void VM_CustomStats_Clear (void)
1561 Z_Free(vm_customstats);
1562 vm_customstats = NULL;
1563 vm_customstats_last = -1;
1567 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1575 for(i=0; i<vm_customstats_last+1 ;i++)
1577 if(!vm_customstats[i].type)
1579 switch(vm_customstats[i].type)
1581 //string as 16 bytes
1584 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1585 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1586 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1587 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1588 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1590 //float field sent as-is
1592 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1594 //integer value of float field
1596 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1604 // void(float index, float type, .void field) SV_AddStat = #232;
1605 // Set up an auto-sent player stat.
1606 // Client's get thier own fields sent to them. Index may not be less than 32.
1607 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1608 // 1: string (4 stats carrying a total of 16 charactures)
1609 // 2: float (one stat, float converted to an integer for transportation)
1610 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1611 static void VM_SV_AddStat (void)
1616 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1620 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1623 VM_Warning("PF_SV_AddStat: not enough memory\n");
1627 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1628 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1629 off = PRVM_G_INT (OFS_PARM2);
1634 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1637 if(i >= (MAX_CL_STATS-32))
1639 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1642 if(i > (MAX_CL_STATS-32-4) && type == 1)
1644 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1647 vm_customstats[i].type = type;
1648 vm_customstats[i].fieldoffset = off;
1649 if(vm_customstats_last < i)
1650 vm_customstats_last = i;
1657 copies data from one entity to another
1659 copyentity(src, dst)
1662 static void VM_SV_copyentity (void)
1664 prvm_edict_t *in, *out;
1665 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1666 in = PRVM_G_EDICT(OFS_PARM0);
1667 if (in == prog->edicts)
1669 VM_Warning("copyentity: can not read world entity\n");
1672 if (in->priv.server->free)
1674 VM_Warning("copyentity: can not read free entity\n");
1677 out = PRVM_G_EDICT(OFS_PARM1);
1678 if (out == prog->edicts)
1680 VM_Warning("copyentity: can not modify world entity\n");
1683 if (out->priv.server->free)
1685 VM_Warning("copyentity: can not modify free entity\n");
1688 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1697 sets the color of a client and broadcasts the update to all connected clients
1699 setcolor(clientent, value)
1702 static void VM_SV_setcolor (void)
1708 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1709 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1710 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1712 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1714 Con_Print("tried to setcolor a non-client\n");
1718 client = svs.clients + entnum-1;
1721 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1723 client->edict->fields.server->team = (i & 15) + 1;
1726 if (client->old_colors != client->colors)
1728 client->old_colors = client->colors;
1729 // send notification to all clients
1730 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1731 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1732 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1740 effect(origin, modelname, startframe, framecount, framerate)
1743 static void VM_SV_effect (void)
1747 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1748 s = PRVM_G_STRING(OFS_PARM1);
1751 VM_Warning("effect: no model specified\n");
1755 i = SV_ModelIndex(s, 1);
1758 VM_Warning("effect: model not precached\n");
1762 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1764 VM_Warning("effect: framecount < 1\n");
1768 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1770 VM_Warning("effect: framerate < 1\n");
1774 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));
1777 static void VM_SV_te_blood (void)
1779 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1780 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1782 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1783 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1785 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1786 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1787 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1789 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1790 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1791 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1793 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1794 SV_FlushBroadcastMessages();
1797 static void VM_SV_te_bloodshower (void)
1799 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1800 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1802 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1803 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1805 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1809 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1810 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1813 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1815 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1816 SV_FlushBroadcastMessages();
1819 static void VM_SV_te_explosionrgb (void)
1821 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1822 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1823 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1825 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1826 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1827 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1829 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1830 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1831 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1832 SV_FlushBroadcastMessages();
1835 static void VM_SV_te_particlecube (void)
1837 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1838 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1840 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1841 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1843 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1844 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1845 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1847 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1848 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1849 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1851 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1852 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1853 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1855 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1857 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1858 // gravity true/false
1859 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1861 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1862 SV_FlushBroadcastMessages();
1865 static void VM_SV_te_particlerain (void)
1867 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1868 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1870 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1871 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1873 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1874 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1875 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1877 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1878 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1879 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1881 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1882 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1883 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1885 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1887 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1888 SV_FlushBroadcastMessages();
1891 static void VM_SV_te_particlesnow (void)
1893 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1894 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1896 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1897 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1900 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1911 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1913 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1914 SV_FlushBroadcastMessages();
1917 static void VM_SV_te_spark (void)
1919 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1920 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1922 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1923 MSG_WriteByte(&sv.datagram, TE_SPARK);
1925 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1926 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1929 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1930 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1931 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1933 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1934 SV_FlushBroadcastMessages();
1937 static void VM_SV_te_gunshotquad (void)
1939 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1940 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1941 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1943 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1944 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1945 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1946 SV_FlushBroadcastMessages();
1949 static void VM_SV_te_spikequad (void)
1951 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1952 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1953 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1955 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1958 SV_FlushBroadcastMessages();
1961 static void VM_SV_te_superspikequad (void)
1963 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1964 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1965 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1970 SV_FlushBroadcastMessages();
1973 static void VM_SV_te_explosionquad (void)
1975 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
1976 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1977 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1979 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1980 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1982 SV_FlushBroadcastMessages();
1985 static void VM_SV_te_smallflash (void)
1987 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
1988 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1989 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1991 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1992 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1993 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1994 SV_FlushBroadcastMessages();
1997 static void VM_SV_te_customflash (void)
1999 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2000 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2002 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2003 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2005 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2006 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2007 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2009 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2011 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2013 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2014 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2015 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2016 SV_FlushBroadcastMessages();
2019 static void VM_SV_te_gunshot (void)
2021 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2022 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2023 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2025 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2026 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2028 SV_FlushBroadcastMessages();
2031 static void VM_SV_te_spike (void)
2033 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2034 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2035 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2037 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2038 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2039 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2040 SV_FlushBroadcastMessages();
2043 static void VM_SV_te_superspike (void)
2045 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2046 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2047 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2049 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2050 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2052 SV_FlushBroadcastMessages();
2055 static void VM_SV_te_explosion (void)
2057 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2058 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2059 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2061 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2062 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2063 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2064 SV_FlushBroadcastMessages();
2067 static void VM_SV_te_tarexplosion (void)
2069 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2070 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2071 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2074 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2075 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2076 SV_FlushBroadcastMessages();
2079 static void VM_SV_te_wizspike (void)
2081 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2082 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2083 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2085 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2086 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2087 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2088 SV_FlushBroadcastMessages();
2091 static void VM_SV_te_knightspike (void)
2093 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2094 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2095 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2097 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2098 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2099 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2100 SV_FlushBroadcastMessages();
2103 static void VM_SV_te_lavasplash (void)
2105 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2106 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2107 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2109 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2110 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2111 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2112 SV_FlushBroadcastMessages();
2115 static void VM_SV_te_teleport (void)
2117 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2118 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2119 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2121 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2122 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2123 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2124 SV_FlushBroadcastMessages();
2127 static void VM_SV_te_explosion2 (void)
2129 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2130 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2131 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2133 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2134 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2135 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2137 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2138 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2139 SV_FlushBroadcastMessages();
2142 static void VM_SV_te_lightning1 (void)
2144 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2145 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2146 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2148 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2150 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2151 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2152 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2154 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2155 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2156 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2157 SV_FlushBroadcastMessages();
2160 static void VM_SV_te_lightning2 (void)
2162 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2163 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2164 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2166 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2168 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2169 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2170 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2172 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2173 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2174 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2175 SV_FlushBroadcastMessages();
2178 static void VM_SV_te_lightning3 (void)
2180 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2181 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2182 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2184 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2186 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2187 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2188 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2190 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2191 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2192 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2193 SV_FlushBroadcastMessages();
2196 static void VM_SV_te_beam (void)
2198 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2199 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2200 MSG_WriteByte(&sv.datagram, TE_BEAM);
2202 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2204 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2205 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2206 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2208 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2209 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2210 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2211 SV_FlushBroadcastMessages();
2214 static void VM_SV_te_plasmaburn (void)
2216 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2217 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2218 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2219 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2220 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2221 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2222 SV_FlushBroadcastMessages();
2225 static void VM_SV_te_flamejet (void)
2227 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2228 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2229 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2231 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2232 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2235 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2236 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2237 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2239 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2240 SV_FlushBroadcastMessages();
2243 void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2246 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2248 bestdist = 1000000000;
2250 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2252 // clip original point to each triangle of the surface and find the
2253 // triangle that is closest
2254 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2255 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2256 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2257 TriangleNormal(v[0], v[1], v[2], facenormal);
2258 VectorNormalize(facenormal);
2259 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2260 VectorMA(p, offsetdist, facenormal, temp);
2261 for (j = 0, k = 2;j < 3;k = j, j++)
2263 VectorSubtract(v[k], v[j], edgenormal);
2264 CrossProduct(edgenormal, facenormal, sidenormal);
2265 VectorNormalize(sidenormal);
2266 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2268 VectorMA(temp, offsetdist, sidenormal, temp);
2270 dist = VectorDistance2(temp, p);
2271 if (bestdist > dist)
2274 VectorCopy(temp, out);
2279 static dp_model_t *getmodel(prvm_edict_t *ed)
2282 if (!ed || ed->priv.server->free)
2284 modelindex = (int)ed->fields.server->modelindex;
2285 if (modelindex < 1 || modelindex >= MAX_MODELS)
2287 return sv.models[modelindex];
2290 static msurface_t *getsurface(dp_model_t *model, int surfacenum)
2292 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2294 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2298 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2299 static void VM_SV_getsurfacenumpoints(void)
2302 msurface_t *surface;
2303 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints);
2304 // return 0 if no such surface
2305 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2307 PRVM_G_FLOAT(OFS_RETURN) = 0;
2311 // note: this (incorrectly) assumes it is a simple polygon
2312 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2314 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2315 static void VM_SV_getsurfacepoint(void)
2319 msurface_t *surface;
2321 VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint);
2322 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2323 ed = PRVM_G_EDICT(OFS_PARM0);
2324 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2326 // note: this (incorrectly) assumes it is a simple polygon
2327 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2328 if (pointnum < 0 || pointnum >= surface->num_vertices)
2330 // FIXME: implement rotation/scaling
2331 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2333 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
2334 // float SPA_POSITION = 0;
2335 // float SPA_S_AXIS = 1;
2336 // float SPA_T_AXIS = 2;
2337 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2338 // float SPA_TEXCOORDS0 = 4;
2339 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2340 // float SPA_LIGHTMAP0_COLOR = 6;
2341 static void VM_SV_getsurfacepointattribute(void)
2345 msurface_t *surface;
2349 VM_SAFEPARMCOUNT(4, VM_SV_getsurfacepoint);
2350 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2351 ed = PRVM_G_EDICT(OFS_PARM0);
2352 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2354 // note: this (incorrectly) assumes it is a simple polygon
2355 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2356 if (pointnum < 0 || pointnum >= surface->num_vertices)
2358 // FIXME: implement rotation/scaling
2359 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
2361 switch( attributetype ) {
2362 // float SPA_POSITION = 0;
2364 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2366 // float SPA_S_AXIS = 1;
2368 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2370 // float SPA_T_AXIS = 2;
2372 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2374 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2376 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2378 // float SPA_TEXCOORDS0 = 4;
2380 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2381 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
2382 ret[0] = texcoord[0];
2383 ret[1] = texcoord[1];
2387 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2389 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2390 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
2391 ret[0] = texcoord[0];
2392 ret[1] = texcoord[1];
2396 // float SPA_LIGHTMAP0_COLOR = 6;
2398 // ignore alpha for now..
2399 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2402 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2406 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2407 static void VM_SV_getsurfacenormal(void)
2410 msurface_t *surface;
2412 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal);
2413 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2414 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2416 // FIXME: implement rotation/scaling
2417 // note: this (incorrectly) assumes it is a simple polygon
2418 // note: this only returns the first triangle, so it doesn't work very
2419 // well for curved surfaces or arbitrary meshes
2420 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);
2421 VectorNormalize(normal);
2422 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2424 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2425 static void VM_SV_getsurfacetexture(void)
2428 msurface_t *surface;
2429 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture);
2430 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2431 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2433 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2435 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2436 static void VM_SV_getsurfacenearpoint(void)
2438 int surfacenum, best;
2440 vec_t dist, bestdist;
2443 msurface_t *surface;
2445 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint);
2446 PRVM_G_FLOAT(OFS_RETURN) = -1;
2447 ed = PRVM_G_EDICT(OFS_PARM0);
2448 point = PRVM_G_VECTOR(OFS_PARM1);
2450 if (!ed || ed->priv.server->free)
2452 model = getmodel(ed);
2453 if (!model || !model->num_surfaces)
2456 // FIXME: implement rotation/scaling
2457 VectorSubtract(point, ed->fields.server->origin, p);
2459 bestdist = 1000000000;
2460 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2462 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2463 // first see if the nearest point on the surface's box is closer than the previous match
2464 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2465 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2466 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2467 dist = VectorLength2(clipped);
2468 if (dist < bestdist)
2470 // it is, check the nearest point on the actual geometry
2471 clippointtosurface(model, surface, p, clipped);
2472 VectorSubtract(clipped, p, clipped);
2473 dist += VectorLength2(clipped);
2474 if (dist < bestdist)
2476 // that's closer too, store it as the best match
2482 PRVM_G_FLOAT(OFS_RETURN) = best;
2484 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2485 static void VM_SV_getsurfaceclippedpoint(void)
2489 msurface_t *surface;
2491 VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint);
2492 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2493 ed = PRVM_G_EDICT(OFS_PARM0);
2494 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2496 // FIXME: implement rotation/scaling
2497 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2498 clippointtosurface(model, surface, p, out);
2499 // FIXME: implement rotation/scaling
2500 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2503 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2504 //this function originally written by KrimZon, made shorter by LordHavoc
2505 static void VM_SV_clientcommand (void)
2507 client_t *temp_client;
2509 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2511 //find client for this entity
2512 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2513 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2515 Con_Print("PF_clientcommand: entity is not a client\n");
2519 temp_client = host_client;
2520 host_client = svs.clients + i;
2521 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2522 host_client = temp_client;
2525 //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)
2526 static void VM_SV_setattachment (void)
2528 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2529 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2530 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2534 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2536 if (e == prog->edicts)
2538 VM_Warning("setattachment: can not modify world entity\n");
2541 if (e->priv.server->free)
2543 VM_Warning("setattachment: can not modify free entity\n");
2547 if (tagentity == NULL)
2548 tagentity = prog->edicts;
2550 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2552 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2554 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2557 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2559 modelindex = (int)tagentity->fields.server->modelindex;
2560 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2562 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2564 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);
2567 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));
2571 /////////////////////////////////////////
2572 // DP_MD3_TAGINFO extension coded by VorteX
2574 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2579 i = (int)e->fields.server->modelindex;
2580 if (i < 1 || i >= MAX_MODELS)
2582 model = sv.models[i];
2584 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2587 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2596 Matrix4x4_CreateIdentity(tag_localmatrix);
2599 && (modelindex = (int)e->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2600 && (model = sv.models[(int)e->fields.server->modelindex])
2601 && model->animscenes)
2603 frame = (int)e->fields.server->frame;
2604 if (frame < 0 || frame >= model->numframes)
2607 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)e->fields.server->skin, model->animscenes[frame].firstframe, tagindex - 1, parentindex, tagname, tag_localmatrix);
2618 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2622 float pitchsign = 1;
2627 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2628 if (val && val->_float != 0)
2629 scale = val->_float;
2632 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);
2636 ((modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[(int)ent->fields.server->modelindex]))
2638 model->type == mod_alias
2641 (((unsigned char)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.pflags)->_float) & PFLAGS_FULLDYNAMIC)
2643 ((gamemode == GAME_TENEBRAE) && ((unsigned int)ent->fields.server->effects & (16 | 32)))
2647 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);
2651 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2657 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2658 && (model = sv.models[(int)ent->fields.server->modelindex])
2659 && model->animscenes)
2661 // if model has wrong frame, engine automatically switches to model first frame
2662 frame = (int)ent->fields.server->frame;
2663 if (frame < 0 || frame >= model->numframes)
2665 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2667 *out = identitymatrix;
2671 // Warnings/errors code:
2672 // 0 - normal (everything all-right)
2675 // 3 - null or non-precached model
2676 // 4 - no tags with requested index
2677 // 5 - runaway loop at attachment chain
2678 extern cvar_t cl_bob;
2679 extern cvar_t cl_bobcycle;
2680 extern cvar_t cl_bobup;
2681 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2685 int modelindex, attachloop;
2686 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2689 *out = identitymatrix; // warnings and errors return identical matrix
2691 if (ent == prog->edicts)
2693 if (ent->priv.server->free)
2696 modelindex = (int)ent->fields.server->modelindex;
2697 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2700 model = sv.models[modelindex];
2702 tagmatrix = identitymatrix;
2703 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2707 if (attachloop >= 256) // prevent runaway looping
2709 // apply transformation by child's tagindex on parent entity and then
2710 // by parent entity itself
2711 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2712 if (ret && attachloop == 0)
2714 SV_GetEntityMatrix(ent, &entitymatrix, false);
2715 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2716 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2717 // next iteration we process the parent entity
2718 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2720 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2721 ent = PRVM_EDICT_NUM(val->edict);
2728 // RENDER_VIEWMODEL magic
2729 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2731 Matrix4x4_Copy(&tagmatrix, out);
2732 ent = PRVM_EDICT_NUM(val->edict);
2734 SV_GetEntityMatrix(ent, &entitymatrix, true);
2735 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2738 // Cl_bob, ported from rendering code
2739 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2742 // LordHavoc: this code is *weird*, but not replacable (I think it
2743 // should be done in QC on the server, but oh well, quake is quake)
2744 // LordHavoc: figured out bobup: the time at which the sin is at 180
2745 // degrees (which allows lengthening or squishing the peak or valley)
2746 cycle = sv.time/cl_bobcycle.value;
2747 cycle -= (int)cycle;
2748 if (cycle < cl_bobup.value)
2749 cycle = sin(M_PI * cycle / cl_bobup.value);
2751 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2752 // bob is proportional to velocity in the xy plane
2753 // (don't count Z, or jumping messes it up)
2754 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;
2755 bob = bob*0.3 + bob*0.7*cycle;
2756 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2763 //float(entity ent, string tagname) gettagindex;
2765 static void VM_SV_gettagindex (void)
2768 const char *tag_name;
2769 int modelindex, tag_index;
2771 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2773 ent = PRVM_G_EDICT(OFS_PARM0);
2774 tag_name = PRVM_G_STRING(OFS_PARM1);
2776 if (ent == prog->edicts)
2778 VM_Warning("gettagindex: can't affect world entity\n");
2781 if (ent->priv.server->free)
2783 VM_Warning("gettagindex: can't affect free entity\n");
2787 modelindex = (int)ent->fields.server->modelindex;
2789 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2790 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2793 tag_index = SV_GetTagIndex(ent, tag_name);
2795 if(developer.integer >= 100)
2796 Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2798 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2801 //vector(entity ent, float tagindex) gettaginfo;
2802 static void VM_SV_gettaginfo (void)
2806 matrix4x4_t tag_matrix;
2807 matrix4x4_t tag_localmatrix;
2809 const char *tagname;
2812 vec3_t fo, le, up, trans;
2814 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2816 e = PRVM_G_EDICT(OFS_PARM0);
2817 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2819 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2820 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, le, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2821 VectorScale(le, -1, prog->globals.server->v_right);
2822 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2823 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2825 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_parent)))
2826 val->_float = parentindex;
2827 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_name)))
2828 val->string = tagname ? PRVM_SetTempString(tagname) : 0;
2829 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_offset)))
2830 VectorCopy(trans, val->vector);
2831 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_forward)))
2832 VectorCopy(fo, val->vector);
2833 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_right)))
2834 VectorScale(le, -1, val->vector);
2835 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_up)))
2836 VectorCopy(up, val->vector);
2841 VM_Warning("gettagindex: can't affect world entity\n");
2844 VM_Warning("gettagindex: can't affect free entity\n");
2847 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2850 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2853 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2858 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2859 static void VM_SV_dropclient (void)
2862 client_t *oldhostclient;
2863 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2864 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2865 if (clientnum < 0 || clientnum >= svs.maxclients)
2867 VM_Warning("dropclient: not a client\n");
2870 if (!svs.clients[clientnum].active)
2872 VM_Warning("dropclient: that client slot is not connected\n");
2875 oldhostclient = host_client;
2876 host_client = svs.clients + clientnum;
2877 SV_DropClient(false);
2878 host_client = oldhostclient;
2881 //entity() spawnclient (DP_SV_BOTCLIENT)
2882 static void VM_SV_spawnclient (void)
2886 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2887 prog->xfunction->builtinsprofile += 2;
2889 for (i = 0;i < svs.maxclients;i++)
2891 if (!svs.clients[i].active)
2893 prog->xfunction->builtinsprofile += 100;
2894 SV_ConnectClient (i, NULL);
2895 // this has to be set or else ClientDisconnect won't be called
2896 // we assume the qc will call ClientConnect...
2897 svs.clients[i].clientconnectcalled = true;
2898 ed = PRVM_EDICT_NUM(i + 1);
2902 VM_RETURN_EDICT(ed);
2905 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2906 static void VM_SV_clienttype (void)
2909 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2910 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2911 if (clientnum < 0 || clientnum >= svs.maxclients)
2912 PRVM_G_FLOAT(OFS_RETURN) = 3;
2913 else if (!svs.clients[clientnum].active)
2914 PRVM_G_FLOAT(OFS_RETURN) = 0;
2915 else if (svs.clients[clientnum].netconnection)
2916 PRVM_G_FLOAT(OFS_RETURN) = 1;
2918 PRVM_G_FLOAT(OFS_RETURN) = 2;
2925 string(string key) serverkey
2928 void VM_SV_serverkey(void)
2930 char string[VM_STRINGTEMP_LENGTH];
2931 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2932 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2933 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2936 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2937 static void VM_SV_setmodelindex (void)
2942 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2944 e = PRVM_G_EDICT(OFS_PARM0);
2945 if (e == prog->edicts)
2947 VM_Warning("setmodelindex: can not modify world entity\n");
2950 if (e->priv.server->free)
2952 VM_Warning("setmodelindex: can not modify free entity\n");
2955 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2956 if (i <= 0 || i >= MAX_MODELS)
2958 VM_Warning("setmodelindex: invalid modelindex\n");
2961 if (!sv.model_precache[i][0])
2963 VM_Warning("setmodelindex: model not precached\n");
2967 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2968 e->fields.server->modelindex = i;
2974 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2975 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2977 SetMinMaxSize (e, quakemins, quakemaxs, true);
2980 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2983 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2984 static void VM_SV_modelnameforindex (void)
2987 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2989 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2991 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2992 if (i <= 0 || i >= MAX_MODELS)
2994 VM_Warning("modelnameforindex: invalid modelindex\n");
2997 if (!sv.model_precache[i][0])
2999 VM_Warning("modelnameforindex: model not precached\n");
3003 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
3006 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
3007 static void VM_SV_particleeffectnum (void)
3010 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
3011 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
3014 PRVM_G_FLOAT(OFS_RETURN) = i;
3017 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3018 static void VM_SV_trailparticles (void)
3020 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
3022 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3025 MSG_WriteByte(&sv.datagram, svc_trailparticles);
3026 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
3027 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
3028 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
3029 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
3030 SV_FlushBroadcastMessages();
3033 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
3034 static void VM_SV_pointparticles (void)
3036 int effectnum, count;
3038 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
3040 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3043 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
3044 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
3045 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
3046 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
3047 if (count == 1 && !VectorLength2(vel))
3050 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
3051 MSG_WriteShort(&sv.datagram, effectnum);
3052 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3056 // 1+2+12+12+2=29 bytes
3057 MSG_WriteByte(&sv.datagram, svc_pointparticles);
3058 MSG_WriteShort(&sv.datagram, effectnum);
3059 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3060 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
3061 MSG_WriteShort(&sv.datagram, count);
3064 SV_FlushBroadcastMessages();
3067 //PF_setpause, // void(float pause) setpause = #531;
3068 static void VM_SV_setpause(void) {
3070 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
3071 if (pauseValue != 0) { //pause the game
3073 sv.pausedstart = Sys_DoubleTime();
3074 } else { //disable pause, in case it was enabled
3075 if (sv.paused != 0) {
3080 // send notification to all clients
3081 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
3082 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
3085 prvm_builtin_t vm_sv_builtins[] = {
3086 NULL, // #0 NULL function (not callable) (QUAKE)
3087 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3088 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3089 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3090 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3091 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3092 VM_break, // #6 void() break (QUAKE)
3093 VM_random, // #7 float() random (QUAKE)
3094 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3095 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3096 VM_error, // #10 void(string e) error (QUAKE)
3097 VM_objerror, // #11 void(string e) objerror (QUAKE)
3098 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3099 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3100 VM_spawn, // #14 entity() spawn (QUAKE)
3101 VM_remove, // #15 void(entity e) remove (QUAKE)
3102 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3103 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3104 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3105 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3106 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3107 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3108 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3109 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3110 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3111 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3112 VM_ftos, // #26 string(float f) ftos (QUAKE)
3113 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3114 VM_coredump, // #28 void() coredump (QUAKE)
3115 VM_traceon, // #29 void() traceon (QUAKE)
3116 VM_traceoff, // #30 void() traceoff (QUAKE)
3117 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3118 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3119 NULL, // #33 (QUAKE)
3120 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3121 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3122 VM_rint, // #36 float(float v) rint (QUAKE)
3123 VM_floor, // #37 float(float v) floor (QUAKE)
3124 VM_ceil, // #38 float(float v) ceil (QUAKE)
3125 NULL, // #39 (QUAKE)
3126 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3127 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3128 NULL, // #42 (QUAKE)
3129 VM_fabs, // #43 float(float f) fabs (QUAKE)
3130 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3131 VM_cvar, // #45 float(string s) cvar (QUAKE)
3132 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3133 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3134 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3135 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3136 NULL, // #50 (QUAKE)
3137 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3138 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3139 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3140 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3141 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3142 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3143 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3144 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3145 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3146 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3147 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3148 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3149 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3150 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3151 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3152 NULL, // #66 (QUAKE)
3153 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3154 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3155 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3156 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3157 NULL, // #71 (QUAKE)
3158 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3159 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3160 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3161 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3162 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3163 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3164 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3165 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3166 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3167 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3168 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3169 NULL, // #83 (QUAKE)
3170 NULL, // #84 (QUAKE)
3171 NULL, // #85 (QUAKE)
3172 NULL, // #86 (QUAKE)
3173 NULL, // #87 (QUAKE)
3174 NULL, // #88 (QUAKE)
3175 NULL, // #89 (QUAKE)
3176 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3177 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3178 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3179 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3180 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3181 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3182 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3183 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3184 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3185 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3186 // FrikaC and Telejano range #100-#199
3197 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3198 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3199 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3200 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3201 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3202 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3203 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3204 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3205 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3206 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3287 // FTEQW range #200-#299
3306 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3309 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3310 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3311 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3312 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3313 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3314 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3315 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3316 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3317 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3318 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3320 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3328 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3388 // CSQC range #300-#399
3389 NULL, // #300 void() clearscene (EXT_CSQC)
3390 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3391 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3392 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3393 NULL, // #304 void() renderscene (EXT_CSQC)
3394 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3395 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3396 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3397 NULL, // #308 void() R_EndPolygon
3399 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3400 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3404 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3405 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3406 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3407 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3408 NULL, // #319 void(string name) freepic (EXT_CSQC)
3409 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3410 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3411 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3412 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3413 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3414 NULL, // #325 void(void) drawresetcliparea
3419 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3420 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3421 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3422 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3423 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3424 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3425 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3426 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3427 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3428 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3429 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3430 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3431 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3432 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3433 NULL, // #344 vector() getmousepos (EXT_CSQC)
3434 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3435 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3436 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3437 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3438 NULL, // #349 float() isdemo (EXT_CSQC)
3439 VM_isserver, // #350 float() isserver (EXT_CSQC)
3440 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3441 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3442 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3443 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3449 NULL, // #360 float() readbyte (EXT_CSQC)
3450 NULL, // #361 float() readchar (EXT_CSQC)
3451 NULL, // #362 float() readshort (EXT_CSQC)
3452 NULL, // #363 float() readlong (EXT_CSQC)
3453 NULL, // #364 float() readcoord (EXT_CSQC)
3454 NULL, // #365 float() readangle (EXT_CSQC)
3455 NULL, // #366 string() readstring (EXT_CSQC)
3456 NULL, // #367 float() readfloat (EXT_CSQC)
3489 // LordHavoc's range #400-#499
3490 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3491 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3492 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3493 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3494 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3495 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3496 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3497 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3498 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)
3499 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3500 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3501 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3502 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3503 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3504 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3505 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3506 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3507 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3508 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3509 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3510 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3511 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3512 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3513 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3514 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3515 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3516 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3517 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3518 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3519 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3520 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3521 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3522 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3523 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3524 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3525 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3526 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3527 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3528 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3529 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3530 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3531 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3532 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3533 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3534 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3535 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3536 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3537 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3538 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3539 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3540 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3541 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3542 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3543 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3544 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3545 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3546 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3547 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3549 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3550 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3551 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3552 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3553 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3554 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3555 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3556 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3557 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3558 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3559 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3561 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3562 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3563 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3564 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3565 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3566 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3567 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3568 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3569 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3570 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3571 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3572 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3573 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3574 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3575 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3576 VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3584 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3585 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3586 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3587 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3588 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3589 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3590 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3591 VM_SV_WritePicture, // #501
3593 VM_whichpack, // #503 string(string) whichpack = #503;
3600 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3601 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3602 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3603 VM_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET)
3604 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3605 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3606 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3607 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3608 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3609 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3621 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3714 VM_getextresponse, // #624 string getextresponse(void)
3718 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3720 void VM_SV_Cmd_Init(void)
3725 void VM_SV_Cmd_Reset(void)
3727 World_End(&sv.world);
3728 if(prog->funcoffsets.SV_Shutdown)
3730 func_t s = prog->funcoffsets.SV_Shutdown;
3731 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3732 PRVM_ExecuteProgram(s,"SV_Shutdown() required");