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;
2625 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2626 if (val && val->_float != 0)
2627 scale = val->_float;
2630 Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2] + ent->fields.server->view_ofs[2], ent->fields.server->v_angle[0], ent->fields.server->v_angle[1], ent->fields.server->v_angle[2], scale * cl_viewmodel_scale.value);
2633 pitchsign = SV_GetPitchSign(ent);
2634 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);
2638 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2644 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2645 && (model = sv.models[(int)ent->fields.server->modelindex])
2646 && model->animscenes)
2648 // if model has wrong frame, engine automatically switches to model first frame
2649 frame = (int)ent->fields.server->frame;
2650 if (frame < 0 || frame >= model->numframes)
2652 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2654 *out = identitymatrix;
2658 // Warnings/errors code:
2659 // 0 - normal (everything all-right)
2662 // 3 - null or non-precached model
2663 // 4 - no tags with requested index
2664 // 5 - runaway loop at attachment chain
2665 extern cvar_t cl_bob;
2666 extern cvar_t cl_bobcycle;
2667 extern cvar_t cl_bobup;
2668 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2672 int modelindex, attachloop;
2673 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2676 *out = identitymatrix; // warnings and errors return identical matrix
2678 if (ent == prog->edicts)
2680 if (ent->priv.server->free)
2683 modelindex = (int)ent->fields.server->modelindex;
2684 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2687 model = sv.models[modelindex];
2689 tagmatrix = identitymatrix;
2690 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2694 if (attachloop >= 256) // prevent runaway looping
2696 // apply transformation by child's tagindex on parent entity and then
2697 // by parent entity itself
2698 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2699 if (ret && attachloop == 0)
2701 SV_GetEntityMatrix(ent, &entitymatrix, false);
2702 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2703 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2704 // next iteration we process the parent entity
2705 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2707 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2708 ent = PRVM_EDICT_NUM(val->edict);
2715 // RENDER_VIEWMODEL magic
2716 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2718 Matrix4x4_Copy(&tagmatrix, out);
2719 ent = PRVM_EDICT_NUM(val->edict);
2721 SV_GetEntityMatrix(ent, &entitymatrix, true);
2722 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2725 // Cl_bob, ported from rendering code
2726 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2729 // LordHavoc: this code is *weird*, but not replacable (I think it
2730 // should be done in QC on the server, but oh well, quake is quake)
2731 // LordHavoc: figured out bobup: the time at which the sin is at 180
2732 // degrees (which allows lengthening or squishing the peak or valley)
2733 cycle = sv.time/cl_bobcycle.value;
2734 cycle -= (int)cycle;
2735 if (cycle < cl_bobup.value)
2736 cycle = sin(M_PI * cycle / cl_bobup.value);
2738 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2739 // bob is proportional to velocity in the xy plane
2740 // (don't count Z, or jumping messes it up)
2741 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;
2742 bob = bob*0.3 + bob*0.7*cycle;
2743 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2750 //float(entity ent, string tagname) gettagindex;
2752 static void VM_SV_gettagindex (void)
2755 const char *tag_name;
2756 int modelindex, tag_index;
2758 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2760 ent = PRVM_G_EDICT(OFS_PARM0);
2761 tag_name = PRVM_G_STRING(OFS_PARM1);
2763 if (ent == prog->edicts)
2765 VM_Warning("gettagindex: can't affect world entity\n");
2768 if (ent->priv.server->free)
2770 VM_Warning("gettagindex: can't affect free entity\n");
2774 modelindex = (int)ent->fields.server->modelindex;
2776 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2777 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2780 tag_index = SV_GetTagIndex(ent, tag_name);
2782 if(developer.integer >= 100)
2783 Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2785 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2788 //vector(entity ent, float tagindex) gettaginfo;
2789 static void VM_SV_gettaginfo (void)
2793 matrix4x4_t tag_matrix;
2794 matrix4x4_t tag_localmatrix;
2796 const char *tagname;
2799 vec3_t fo, le, up, trans;
2801 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2803 e = PRVM_G_EDICT(OFS_PARM0);
2804 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2806 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2807 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, le, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2808 VectorScale(le, -1, prog->globals.server->v_right);
2809 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2810 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2812 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_parent)))
2813 val->_float = parentindex;
2814 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_name)))
2815 val->string = tagname ? PRVM_SetTempString(tagname) : 0;
2816 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_offset)))
2817 VectorCopy(trans, val->vector);
2818 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_forward)))
2819 VectorCopy(fo, val->vector);
2820 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_right)))
2821 VectorScale(le, -1, val->vector);
2822 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_up)))
2823 VectorCopy(up, val->vector);
2828 VM_Warning("gettagindex: can't affect world entity\n");
2831 VM_Warning("gettagindex: can't affect free entity\n");
2834 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2837 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2840 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2845 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2846 static void VM_SV_dropclient (void)
2849 client_t *oldhostclient;
2850 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2851 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2852 if (clientnum < 0 || clientnum >= svs.maxclients)
2854 VM_Warning("dropclient: not a client\n");
2857 if (!svs.clients[clientnum].active)
2859 VM_Warning("dropclient: that client slot is not connected\n");
2862 oldhostclient = host_client;
2863 host_client = svs.clients + clientnum;
2864 SV_DropClient(false);
2865 host_client = oldhostclient;
2868 //entity() spawnclient (DP_SV_BOTCLIENT)
2869 static void VM_SV_spawnclient (void)
2873 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2874 prog->xfunction->builtinsprofile += 2;
2876 for (i = 0;i < svs.maxclients;i++)
2878 if (!svs.clients[i].active)
2880 prog->xfunction->builtinsprofile += 100;
2881 SV_ConnectClient (i, NULL);
2882 // this has to be set or else ClientDisconnect won't be called
2883 // we assume the qc will call ClientConnect...
2884 svs.clients[i].clientconnectcalled = true;
2885 ed = PRVM_EDICT_NUM(i + 1);
2889 VM_RETURN_EDICT(ed);
2892 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2893 static void VM_SV_clienttype (void)
2896 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2897 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2898 if (clientnum < 0 || clientnum >= svs.maxclients)
2899 PRVM_G_FLOAT(OFS_RETURN) = 3;
2900 else if (!svs.clients[clientnum].active)
2901 PRVM_G_FLOAT(OFS_RETURN) = 0;
2902 else if (svs.clients[clientnum].netconnection)
2903 PRVM_G_FLOAT(OFS_RETURN) = 1;
2905 PRVM_G_FLOAT(OFS_RETURN) = 2;
2912 string(string key) serverkey
2915 void VM_SV_serverkey(void)
2917 char string[VM_STRINGTEMP_LENGTH];
2918 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2919 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2920 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2923 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2924 static void VM_SV_setmodelindex (void)
2929 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2931 e = PRVM_G_EDICT(OFS_PARM0);
2932 if (e == prog->edicts)
2934 VM_Warning("setmodelindex: can not modify world entity\n");
2937 if (e->priv.server->free)
2939 VM_Warning("setmodelindex: can not modify free entity\n");
2942 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2943 if (i <= 0 || i >= MAX_MODELS)
2945 VM_Warning("setmodelindex: invalid modelindex\n");
2948 if (!sv.model_precache[i][0])
2950 VM_Warning("setmodelindex: model not precached\n");
2954 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2955 e->fields.server->modelindex = i;
2961 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2962 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2964 SetMinMaxSize (e, quakemins, quakemaxs, true);
2967 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2970 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2971 static void VM_SV_modelnameforindex (void)
2974 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2976 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2978 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2979 if (i <= 0 || i >= MAX_MODELS)
2981 VM_Warning("modelnameforindex: invalid modelindex\n");
2984 if (!sv.model_precache[i][0])
2986 VM_Warning("modelnameforindex: model not precached\n");
2990 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2993 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2994 static void VM_SV_particleeffectnum (void)
2997 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2998 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
3001 PRVM_G_FLOAT(OFS_RETURN) = i;
3004 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3005 static void VM_SV_trailparticles (void)
3007 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
3009 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3012 MSG_WriteByte(&sv.datagram, svc_trailparticles);
3013 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
3014 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
3015 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
3016 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
3017 SV_FlushBroadcastMessages();
3020 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
3021 static void VM_SV_pointparticles (void)
3023 int effectnum, count;
3025 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
3027 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3030 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
3031 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
3032 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
3033 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
3034 if (count == 1 && !VectorLength2(vel))
3037 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
3038 MSG_WriteShort(&sv.datagram, effectnum);
3039 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3043 // 1+2+12+12+2=29 bytes
3044 MSG_WriteByte(&sv.datagram, svc_pointparticles);
3045 MSG_WriteShort(&sv.datagram, effectnum);
3046 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3047 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
3048 MSG_WriteShort(&sv.datagram, count);
3051 SV_FlushBroadcastMessages();
3054 //PF_setpause, // void(float pause) setpause = #531;
3055 static void VM_SV_setpause(void) {
3057 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
3058 if (pauseValue != 0) { //pause the game
3060 sv.pausedstart = Sys_DoubleTime();
3061 } else { //disable pause, in case it was enabled
3062 if (sv.paused != 0) {
3067 // send notification to all clients
3068 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
3069 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
3072 prvm_builtin_t vm_sv_builtins[] = {
3073 NULL, // #0 NULL function (not callable) (QUAKE)
3074 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3075 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3076 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3077 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3078 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3079 VM_break, // #6 void() break (QUAKE)
3080 VM_random, // #7 float() random (QUAKE)
3081 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3082 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3083 VM_error, // #10 void(string e) error (QUAKE)
3084 VM_objerror, // #11 void(string e) objerror (QUAKE)
3085 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3086 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3087 VM_spawn, // #14 entity() spawn (QUAKE)
3088 VM_remove, // #15 void(entity e) remove (QUAKE)
3089 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3090 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3091 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3092 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3093 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3094 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3095 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3096 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3097 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3098 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3099 VM_ftos, // #26 string(float f) ftos (QUAKE)
3100 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3101 VM_coredump, // #28 void() coredump (QUAKE)
3102 VM_traceon, // #29 void() traceon (QUAKE)
3103 VM_traceoff, // #30 void() traceoff (QUAKE)
3104 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3105 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3106 NULL, // #33 (QUAKE)
3107 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3108 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3109 VM_rint, // #36 float(float v) rint (QUAKE)
3110 VM_floor, // #37 float(float v) floor (QUAKE)
3111 VM_ceil, // #38 float(float v) ceil (QUAKE)
3112 NULL, // #39 (QUAKE)
3113 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3114 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3115 NULL, // #42 (QUAKE)
3116 VM_fabs, // #43 float(float f) fabs (QUAKE)
3117 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3118 VM_cvar, // #45 float(string s) cvar (QUAKE)
3119 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3120 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3121 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3122 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3123 NULL, // #50 (QUAKE)
3124 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3125 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3126 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3127 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3128 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3129 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3130 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3131 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3132 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3133 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3134 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3135 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3136 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3137 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3138 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3139 NULL, // #66 (QUAKE)
3140 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3141 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3142 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3143 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3144 NULL, // #71 (QUAKE)
3145 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3146 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3147 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3148 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3149 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3150 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3151 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3152 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3153 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3154 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3155 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3156 NULL, // #83 (QUAKE)
3157 NULL, // #84 (QUAKE)
3158 NULL, // #85 (QUAKE)
3159 NULL, // #86 (QUAKE)
3160 NULL, // #87 (QUAKE)
3161 NULL, // #88 (QUAKE)
3162 NULL, // #89 (QUAKE)
3163 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3164 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3165 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3166 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3167 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3168 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3169 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3170 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3171 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3172 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3173 // FrikaC and Telejano range #100-#199
3184 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3185 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3186 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3187 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3188 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3189 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3190 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3191 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3192 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3193 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3274 // FTEQW range #200-#299
3293 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3296 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3297 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3298 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3299 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3300 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3301 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3302 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3303 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3304 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3305 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3307 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3315 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3375 // CSQC range #300-#399
3376 NULL, // #300 void() clearscene (EXT_CSQC)
3377 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3378 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3379 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3380 NULL, // #304 void() renderscene (EXT_CSQC)
3381 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3382 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3383 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3384 NULL, // #308 void() R_EndPolygon
3386 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3387 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3391 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3392 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3393 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3394 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3395 NULL, // #319 void(string name) freepic (EXT_CSQC)
3396 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3397 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3398 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3399 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3400 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3401 NULL, // #325 void(void) drawresetcliparea
3406 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3407 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3408 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3409 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3410 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3411 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3412 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3413 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3414 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3415 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3416 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3417 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3418 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3419 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3420 NULL, // #344 vector() getmousepos (EXT_CSQC)
3421 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3422 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3423 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3424 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3425 NULL, // #349 float() isdemo (EXT_CSQC)
3426 VM_isserver, // #350 float() isserver (EXT_CSQC)
3427 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3428 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3429 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3430 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3436 NULL, // #360 float() readbyte (EXT_CSQC)
3437 NULL, // #361 float() readchar (EXT_CSQC)
3438 NULL, // #362 float() readshort (EXT_CSQC)
3439 NULL, // #363 float() readlong (EXT_CSQC)
3440 NULL, // #364 float() readcoord (EXT_CSQC)
3441 NULL, // #365 float() readangle (EXT_CSQC)
3442 NULL, // #366 string() readstring (EXT_CSQC)
3443 NULL, // #367 float() readfloat (EXT_CSQC)
3476 // LordHavoc's range #400-#499
3477 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3478 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3479 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3480 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3481 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3482 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3483 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3484 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3485 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)
3486 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3487 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3488 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3489 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3490 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3491 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3492 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3493 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3494 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3495 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3496 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3497 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3498 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3499 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3500 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3501 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3502 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3503 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3504 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3505 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3506 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3507 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3508 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3509 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3510 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3511 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3512 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3513 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3514 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3515 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3516 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3517 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3518 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3519 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3520 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3521 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3522 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3523 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3524 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3525 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3526 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3527 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3528 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3529 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3530 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3531 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3532 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3533 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3534 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3536 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3537 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3538 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3539 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3540 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3541 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3542 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3543 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3544 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3545 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3546 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3548 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3549 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3550 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3551 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3552 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3553 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3554 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3555 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3556 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3557 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3558 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3559 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3560 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3561 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3562 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3563 VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3571 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3572 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3573 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3574 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3575 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3576 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3577 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3578 VM_SV_WritePicture, // #501
3580 VM_whichpack, // #503 string(string) whichpack = #503;
3587 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3588 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3589 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3590 VM_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET)
3591 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3592 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3593 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3594 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3595 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3596 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3608 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3701 VM_getextresponse, // #624 string getextresponse(void)
3705 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3707 void VM_SV_Cmd_Init(void)
3712 void VM_SV_Cmd_Reset(void)
3714 World_End(&sv.world);
3715 if(prog->funcoffsets.SV_Shutdown)
3717 func_t s = prog->funcoffsets.SV_Shutdown;
3718 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3719 PRVM_ExecuteProgram(s,"SV_Shutdown() required");