5 //============================================================================
10 char *vm_sv_extensions =
15 "DP_CON_ALIASPARAMETERS "
33 "DP_ENT_CUSTOMCOLORMAP "
34 "DP_ENT_EXTERIORMODELTOCLIENT "
36 "DP_ENT_LOWPRECISION "
39 "DP_GFX_EXTERNALTEXTURES "
40 "DP_GFX_EXTERNALTEXTURES_PERMAP "
42 "DP_GFX_QUAKE3MODELTAGS "
46 "DP_HALFLIFE_MAP_CVAR "
52 "DP_MOVETYPEBOUNCEMISSILE "
54 "DP_QC_ASINACOSATANATAN2TAN "
57 "DP_QC_CVAR_DEFSTRING "
63 "DP_QC_FINDCHAINFLAGS "
64 "DP_QC_FINDCHAINFLOAT "
72 "DP_QC_MULTIPLETEMPSTRINGS "
74 "DP_QC_SINCOSSQRTPOW "
76 "DP_QC_STRING_CASE_FUNCTIONS "
77 "DP_QC_STRINGBUFFERS "
78 "DP_QC_STRINGCOLORFUNCTIONS "
79 "DP_QC_TOKENIZEBYSEPARATOR "
82 "DP_QC_TRACE_MOVETYPE_HITMODEL "
83 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
84 "DP_QC_UNLIMITEDTEMPSTRINGS "
85 "DP_QC_VECTOANGLES_WITH_ROLL "
86 "DP_QC_VECTORVECTORS "
92 "DP_SND_DIRECTIONLESSATTNNONE "
101 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
102 "DP_SV_DRAWONLYTOCLIENT "
105 "DP_SV_ENTITYCONTENTSTRANSITION "
106 "DP_SV_ONENTITYNOSPAWNFUNCTION "
107 "DP_SV_MODELFLAGS_AS_EFFECTS "
109 "DP_SV_NODRAWTOCLIENT "
111 "DP_SV_PLAYERPHYSICS "
112 "DP_SV_POINTPARTICLES "
114 "DP_SV_PRECACHEANYTIME "
117 "DP_SV_ROTATINGBMODEL "
120 "DP_SV_WRITEUNTERMINATEDSTRING "
124 "DP_TE_EXPLOSIONRGB "
126 "DP_TE_PARTICLECUBE "
127 "DP_TE_PARTICLERAIN "
128 "DP_TE_PARTICLESNOW "
130 "DP_TE_QUADEFFECTS1 "
133 "DP_TE_STANDARDEFFECTBUILTINS "
134 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
137 //"EXT_CSQC " // not ready yet
139 "KRIMZON_SV_PARSECLIENTCOMMAND "
142 "NEXUIZ_PLAYERMODEL "
144 "PRYDON_CLIENTCURSOR "
145 "TENEBRAE_GFX_DLIGHTS "
155 "DP_QC_GETSURFACEPOINTATTRIBUTE "
162 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.
164 setorigin (entity, origin)
167 static void VM_SV_setorigin (void)
172 VM_SAFEPARMCOUNT(2, VM_setorigin);
174 e = PRVM_G_EDICT(OFS_PARM0);
175 if (e == prog->edicts)
177 VM_Warning("setorigin: can not modify world entity\n");
180 if (e->priv.server->free)
182 VM_Warning("setorigin: can not modify free entity\n");
185 org = PRVM_G_VECTOR(OFS_PARM1);
186 VectorCopy (org, e->fields.server->origin);
187 SV_LinkEdict (e, false);
190 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
191 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
195 for (i=0 ; i<3 ; i++)
197 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
199 // set derived values
200 VectorCopy (min, e->fields.server->mins);
201 VectorCopy (max, e->fields.server->maxs);
202 VectorSubtract (max, min, e->fields.server->size);
204 SV_LinkEdict (e, false);
211 the size box is rotated by the current angle
212 LordHavoc: no it isn't...
214 setsize (entity, minvector, maxvector)
217 static void VM_SV_setsize (void)
222 VM_SAFEPARMCOUNT(3, VM_setsize);
224 e = PRVM_G_EDICT(OFS_PARM0);
225 if (e == prog->edicts)
227 VM_Warning("setsize: can not modify world entity\n");
230 if (e->priv.server->free)
232 VM_Warning("setsize: can not modify free entity\n");
235 min = PRVM_G_VECTOR(OFS_PARM1);
236 max = PRVM_G_VECTOR(OFS_PARM2);
237 SetMinMaxSize (e, min, max, false);
245 setmodel(entity, model)
248 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
249 static void VM_SV_setmodel (void)
255 VM_SAFEPARMCOUNT(2, VM_setmodel);
257 e = PRVM_G_EDICT(OFS_PARM0);
258 if (e == prog->edicts)
260 VM_Warning("setmodel: can not modify world entity\n");
263 if (e->priv.server->free)
265 VM_Warning("setmodel: can not modify free entity\n");
268 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
269 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
270 e->fields.server->modelindex = i;
276 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
277 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
279 SetMinMaxSize (e, quakemins, quakemaxs, true);
282 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
289 single print to a specific client
291 sprint(clientent, value)
294 static void VM_SV_sprint (void)
298 char string[VM_STRINGTEMP_LENGTH];
300 VM_VarString(1, string, sizeof(string));
302 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
304 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
305 // LordHavoc: div0 requested that sprintto world operate like print
312 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
314 VM_Warning("tried to centerprint to a non-client\n");
318 client = svs.clients + entnum-1;
319 if (!client->netconnection)
322 MSG_WriteChar(&client->netconnection->message,svc_print);
323 MSG_WriteString(&client->netconnection->message, string);
331 single print to a specific client
333 centerprint(clientent, value)
336 static void VM_SV_centerprint (void)
340 char string[VM_STRINGTEMP_LENGTH];
342 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
344 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
346 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
348 VM_Warning("tried to centerprint to a non-client\n");
352 client = svs.clients + entnum-1;
353 if (!client->netconnection)
356 VM_VarString(1, string, sizeof(string));
357 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
358 MSG_WriteString(&client->netconnection->message, string);
365 particle(origin, color, count)
368 static void VM_SV_particle (void)
374 VM_SAFEPARMCOUNT(4, VM_SV_particle);
376 org = PRVM_G_VECTOR(OFS_PARM0);
377 dir = PRVM_G_VECTOR(OFS_PARM1);
378 color = PRVM_G_FLOAT(OFS_PARM2);
379 count = PRVM_G_FLOAT(OFS_PARM3);
380 SV_StartParticle (org, dir, (int)color, (int)count);
390 static void VM_SV_ambientsound (void)
394 float vol, attenuation;
397 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
399 pos = PRVM_G_VECTOR (OFS_PARM0);
400 samp = PRVM_G_STRING(OFS_PARM1);
401 vol = PRVM_G_FLOAT(OFS_PARM2);
402 attenuation = PRVM_G_FLOAT(OFS_PARM3);
404 // check to see if samp was properly precached
405 soundnum = SV_SoundIndex(samp, 1);
413 // add an svc_spawnambient command to the level signon packet
416 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
418 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
420 MSG_WriteVector(&sv.signon, pos, sv.protocol);
422 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
423 MSG_WriteShort (&sv.signon, soundnum);
425 MSG_WriteByte (&sv.signon, soundnum);
427 MSG_WriteByte (&sv.signon, (int)(vol*255));
428 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
436 Each entity can have eight independant sound sources, like voice,
439 Channel 0 is an auto-allocate channel, the others override anything
440 already running on that entity/channel pair.
442 An attenuation of 0 will play full volume everywhere in the level.
443 Larger attenuations will drop off.
447 static void VM_SV_sound (void)
451 prvm_edict_t *entity;
455 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
457 entity = PRVM_G_EDICT(OFS_PARM0);
458 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
459 sample = PRVM_G_STRING(OFS_PARM2);
460 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
461 attenuation = PRVM_G_FLOAT(OFS_PARM4);
464 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
468 if (volume < 0 || volume > 255)
470 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
474 if (attenuation < 0 || attenuation > 4)
476 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
480 if (channel < 0 || channel > 7)
482 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
486 SV_StartSound (entity, channel, sample, volume, attenuation);
493 Follows the same logic as VM_SV_sound, except instead of
494 an entity, an origin for the sound is provided, and channel
495 is omitted (since no entity is being tracked).
499 static void VM_SV_pointsound(void)
506 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
508 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
509 sample = PRVM_G_STRING(OFS_PARM1);
510 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
511 attenuation = PRVM_G_FLOAT(OFS_PARM3);
513 if (volume < 0 || volume > 255)
515 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
519 if (attenuation < 0 || attenuation > 4)
521 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
525 SV_StartPointSound (org, sample, volume, attenuation);
532 Used for use tracing and shot targeting
533 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
534 if the tryents flag is set.
536 traceline (vector1, vector2, movetype, ignore)
539 static void VM_SV_traceline (void)
546 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
548 prog->xfunction->builtinsprofile += 30;
550 v1 = PRVM_G_VECTOR(OFS_PARM0);
551 v2 = PRVM_G_VECTOR(OFS_PARM1);
552 move = (int)PRVM_G_FLOAT(OFS_PARM2);
553 ent = PRVM_G_EDICT(OFS_PARM3);
555 if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2]))
556 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));
558 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
560 VM_SetTraceGlobals(&trace);
568 Used for use tracing and shot targeting
569 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
570 if the tryents flag is set.
572 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
575 // LordHavoc: added this for my own use, VERY useful, similar to traceline
576 static void VM_SV_tracebox (void)
578 float *v1, *v2, *m1, *m2;
583 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
585 prog->xfunction->builtinsprofile += 30;
587 v1 = PRVM_G_VECTOR(OFS_PARM0);
588 m1 = PRVM_G_VECTOR(OFS_PARM1);
589 m2 = PRVM_G_VECTOR(OFS_PARM2);
590 v2 = PRVM_G_VECTOR(OFS_PARM3);
591 move = (int)PRVM_G_FLOAT(OFS_PARM4);
592 ent = PRVM_G_EDICT(OFS_PARM5);
594 if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2]))
595 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));
597 trace = SV_Move (v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
599 VM_SetTraceGlobals(&trace);
602 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
607 vec3_t original_origin;
608 vec3_t original_velocity;
609 vec3_t original_angles;
610 vec3_t original_avelocity;
614 VectorCopy(tossent->fields.server->origin , original_origin );
615 VectorCopy(tossent->fields.server->velocity , original_velocity );
616 VectorCopy(tossent->fields.server->angles , original_angles );
617 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
619 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
620 if (val != NULL && val->_float != 0)
621 gravity = val->_float;
624 gravity *= sv_gravity.value * 0.05;
626 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
628 SV_CheckVelocity (tossent);
629 tossent->fields.server->velocity[2] -= gravity;
630 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
631 VectorScale (tossent->fields.server->velocity, 0.05, move);
632 VectorAdd (tossent->fields.server->origin, move, end);
633 trace = SV_Move (tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
634 VectorCopy (trace.endpos, tossent->fields.server->origin);
636 if (trace.fraction < 1)
640 VectorCopy(original_origin , tossent->fields.server->origin );
641 VectorCopy(original_velocity , tossent->fields.server->velocity );
642 VectorCopy(original_angles , tossent->fields.server->angles );
643 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
648 static void VM_SV_tracetoss (void)
652 prvm_edict_t *ignore;
654 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
656 prog->xfunction->builtinsprofile += 600;
658 ent = PRVM_G_EDICT(OFS_PARM0);
659 if (ent == prog->edicts)
661 VM_Warning("tracetoss: can not use world entity\n");
664 ignore = PRVM_G_EDICT(OFS_PARM1);
666 trace = SV_Trace_Toss (ent, ignore);
668 VM_SetTraceGlobals(&trace);
671 //============================================================================
673 static int checkpvsbytes;
674 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
676 static int VM_SV_newcheckclient (int check)
682 // cycle to the next one
684 check = bound(1, check, svs.maxclients);
685 if (check == svs.maxclients)
693 prog->xfunction->builtinsprofile++;
695 if (i == svs.maxclients+1)
697 // look up the client's edict
698 ent = PRVM_EDICT_NUM(i);
699 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
700 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
702 // found a valid client (possibly the same one again)
706 // get the PVS for the entity
707 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
709 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
710 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
719 Returns a client (or object that has a client enemy) that would be a
722 If there is more than one valid option, they are cycled each frame
724 If (self.origin + self.viewofs) is not in the PVS of the current target,
725 it is not returned at all.
730 int c_invis, c_notvis;
731 static void VM_SV_checkclient (void)
733 prvm_edict_t *ent, *self;
736 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
738 // find a new check if on a new frame
739 if (sv.time - sv.lastchecktime >= 0.1)
741 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
742 sv.lastchecktime = sv.time;
745 // return check if it might be visible
746 ent = PRVM_EDICT_NUM(sv.lastcheck);
747 if (ent->priv.server->free || ent->fields.server->health <= 0)
749 VM_RETURN_EDICT(prog->edicts);
753 // if current entity can't possibly see the check entity, return 0
754 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
755 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
756 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
759 VM_RETURN_EDICT(prog->edicts);
763 // might be able to see it
765 VM_RETURN_EDICT(ent);
768 //============================================================================
775 Sends text over to the client's execution buffer
777 stuffcmd (clientent, value, ...)
780 static void VM_SV_stuffcmd (void)
784 char string[VM_STRINGTEMP_LENGTH];
786 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
788 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
789 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
791 VM_Warning("Can't stuffcmd to a non-client\n");
795 VM_VarString(1, string, sizeof(string));
798 host_client = svs.clients + entnum-1;
799 Host_ClientCommands ("%s", string);
807 Returns a chain of entities that have origins within a spherical area
809 findradius (origin, radius)
812 static void VM_SV_findradius (void)
814 prvm_edict_t *ent, *chain;
815 vec_t radius, radius2;
816 vec3_t org, eorg, mins, maxs;
819 prvm_edict_t *touchedicts[MAX_EDICTS];
821 VM_SAFEPARMCOUNT(2, VM_SV_findradius);
823 chain = (prvm_edict_t *)prog->edicts;
825 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
826 radius = PRVM_G_FLOAT(OFS_PARM1);
827 radius2 = radius * radius;
829 mins[0] = org[0] - (radius + 1);
830 mins[1] = org[1] - (radius + 1);
831 mins[2] = org[2] - (radius + 1);
832 maxs[0] = org[0] + (radius + 1);
833 maxs[1] = org[1] + (radius + 1);
834 maxs[2] = org[2] + (radius + 1);
835 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
836 if (numtouchedicts > MAX_EDICTS)
838 // this never happens
839 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
840 numtouchedicts = MAX_EDICTS;
842 for (i = 0;i < numtouchedicts;i++)
844 ent = touchedicts[i];
845 prog->xfunction->builtinsprofile++;
846 // Quake did not return non-solid entities but darkplaces does
847 // (note: this is the reason you can't blow up fallen zombies)
848 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
850 // LordHavoc: compare against bounding box rather than center so it
851 // doesn't miss large objects, and use DotProduct instead of Length
852 // for a major speedup
853 VectorSubtract(org, ent->fields.server->origin, eorg);
854 if (sv_gameplayfix_findradiusdistancetobox.integer)
856 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
857 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
858 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
861 VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
862 if (DotProduct(eorg, eorg) < radius2)
864 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
869 VM_RETURN_EDICT(chain);
872 static void VM_SV_precache_sound (void)
874 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
875 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
878 static void VM_SV_precache_model (void)
880 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
881 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
882 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
889 float(float yaw, float dist[, settrace]) walkmove
892 static void VM_SV_walkmove (void)
901 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
903 // assume failure if it returns early
904 PRVM_G_FLOAT(OFS_RETURN) = 0;
906 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
907 if (ent == prog->edicts)
909 VM_Warning("walkmove: can not modify world entity\n");
912 if (ent->priv.server->free)
914 VM_Warning("walkmove: can not modify free entity\n");
917 yaw = PRVM_G_FLOAT(OFS_PARM0);
918 dist = PRVM_G_FLOAT(OFS_PARM1);
919 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
921 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
924 yaw = yaw*M_PI*2 / 360;
926 move[0] = cos(yaw)*dist;
927 move[1] = sin(yaw)*dist;
930 // save program state, because SV_movestep may call other progs
931 oldf = prog->xfunction;
932 oldself = prog->globals.server->self;
934 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
937 // restore program state
938 prog->xfunction = oldf;
939 prog->globals.server->self = oldself;
949 static void VM_SV_droptofloor (void)
955 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
957 // assume failure if it returns early
958 PRVM_G_FLOAT(OFS_RETURN) = 0;
960 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
961 if (ent == prog->edicts)
963 VM_Warning("droptofloor: can not modify world entity\n");
966 if (ent->priv.server->free)
968 VM_Warning("droptofloor: can not modify free entity\n");
972 VectorCopy (ent->fields.server->origin, end);
975 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
976 SV_UnstickEntity(ent);
978 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
979 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
982 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]);
983 VectorAdd(ent->fields.server->origin, offset, org);
984 trace = SV_Move (org, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
985 VectorSubtract(trace.endpos, offset, trace.endpos);
986 if (trace.startsolid)
988 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]);
989 SV_UnstickEntity(ent);
990 SV_LinkEdict (ent, false);
991 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
992 ent->fields.server->groundentity = 0;
993 PRVM_G_FLOAT(OFS_RETURN) = 1;
995 else if (trace.fraction < 1)
997 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]);
998 VectorCopy (trace.endpos, ent->fields.server->origin);
999 SV_UnstickEntity(ent);
1000 SV_LinkEdict (ent, false);
1001 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1002 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1003 PRVM_G_FLOAT(OFS_RETURN) = 1;
1004 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1005 ent->priv.server->suspendedinairflag = true;
1010 if (trace.fraction != 1)
1012 if (trace.fraction < 1)
1013 VectorCopy (trace.endpos, ent->fields.server->origin);
1014 SV_LinkEdict (ent, false);
1015 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1016 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1017 PRVM_G_FLOAT(OFS_RETURN) = 1;
1018 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1019 ent->priv.server->suspendedinairflag = true;
1028 void(float style, string value) lightstyle
1031 static void VM_SV_lightstyle (void)
1038 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1040 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1041 val = PRVM_G_STRING(OFS_PARM1);
1043 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1044 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1047 // change the string in sv
1048 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1050 // send message to all clients on this server
1051 if (sv.state != ss_active)
1054 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1056 if (client->active && client->netconnection)
1058 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1059 MSG_WriteChar (&client->netconnection->message,style);
1060 MSG_WriteString (&client->netconnection->message, val);
1070 static void VM_SV_checkbottom (void)
1072 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1073 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1081 static void VM_SV_pointcontents (void)
1083 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1084 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1091 Pick a vector for the player to shoot along
1092 vector aim(entity, missilespeed)
1095 static void VM_SV_aim (void)
1097 prvm_edict_t *ent, *check, *bestent;
1098 vec3_t start, dir, end, bestdir;
1101 float dist, bestdist;
1104 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1106 // assume failure if it returns early
1107 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1108 // if sv_aim is so high it can't possibly accept anything, skip out early
1109 if (sv_aim.value >= 1)
1112 ent = PRVM_G_EDICT(OFS_PARM0);
1113 if (ent == prog->edicts)
1115 VM_Warning("aim: can not use world entity\n");
1118 if (ent->priv.server->free)
1120 VM_Warning("aim: can not use free entity\n");
1123 speed = PRVM_G_FLOAT(OFS_PARM1);
1125 VectorCopy (ent->fields.server->origin, start);
1128 // try sending a trace straight
1129 VectorCopy (prog->globals.server->v_forward, dir);
1130 VectorMA (start, 2048, dir, end);
1131 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1132 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1133 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1135 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1140 // try all possible entities
1141 VectorCopy (dir, bestdir);
1142 bestdist = sv_aim.value;
1145 check = PRVM_NEXT_EDICT(prog->edicts);
1146 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1148 prog->xfunction->builtinsprofile++;
1149 if (check->fields.server->takedamage != DAMAGE_AIM)
1153 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1154 continue; // don't aim at teammate
1155 for (j=0 ; j<3 ; j++)
1156 end[j] = check->fields.server->origin[j]
1157 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1158 VectorSubtract (end, start, dir);
1159 VectorNormalize (dir);
1160 dist = DotProduct (dir, prog->globals.server->v_forward);
1161 if (dist < bestdist)
1162 continue; // to far to turn
1163 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1164 if (tr.ent == check)
1165 { // can shoot at this one
1173 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1174 dist = DotProduct (dir, prog->globals.server->v_forward);
1175 VectorScale (prog->globals.server->v_forward, dist, end);
1177 VectorNormalize (end);
1178 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1182 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1187 ===============================================================================
1191 ===============================================================================
1194 #define MSG_BROADCAST 0 // unreliable to all
1195 #define MSG_ONE 1 // reliable to one (msg_entity)
1196 #define MSG_ALL 2 // reliable to all
1197 #define MSG_INIT 3 // write to the init string
1198 #define MSG_ENTITY 5
1200 sizebuf_t *WriteDest (void)
1206 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1210 return &sv.datagram;
1213 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1214 entnum = PRVM_NUM_FOR_EDICT(ent);
1215 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1217 VM_Warning ("WriteDest: tried to write to non-client\n");
1218 return &sv.reliable_datagram;
1221 return &svs.clients[entnum-1].netconnection->message;
1224 VM_Warning ("WriteDest: bad destination\n");
1226 return &sv.reliable_datagram;
1232 return sv.writeentitiestoclient_msg;
1238 static void VM_SV_WriteByte (void)
1240 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1241 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1244 static void VM_SV_WriteChar (void)
1246 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1247 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1250 static void VM_SV_WriteShort (void)
1252 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1253 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1256 static void VM_SV_WriteLong (void)
1258 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1259 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1262 static void VM_SV_WriteAngle (void)
1264 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1265 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1268 static void VM_SV_WriteCoord (void)
1270 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1271 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1274 static void VM_SV_WriteString (void)
1276 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1277 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1280 static void VM_SV_WriteUnterminatedString (void)
1282 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1283 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1287 static void VM_SV_WriteEntity (void)
1289 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1290 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1293 //////////////////////////////////////////////////////////
1295 static void VM_SV_makestatic (void)
1300 // allow 0 parameters due to an id1 qc bug in which this function is used
1301 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1302 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1304 if (prog->argc >= 1)
1305 ent = PRVM_G_EDICT(OFS_PARM0);
1307 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1308 if (ent == prog->edicts)
1310 VM_Warning("makestatic: can not modify world entity\n");
1313 if (ent->priv.server->free)
1315 VM_Warning("makestatic: can not modify free entity\n");
1320 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1325 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1326 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1327 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1329 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1331 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1332 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1333 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1337 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1338 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1339 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1342 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1343 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1344 for (i=0 ; i<3 ; i++)
1346 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1347 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1350 // throw the entity away now
1354 //=============================================================================
1361 static void VM_SV_setspawnparms (void)
1367 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1369 ent = PRVM_G_EDICT(OFS_PARM0);
1370 i = PRVM_NUM_FOR_EDICT(ent);
1371 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1373 Con_Print("tried to setspawnparms on a non-client\n");
1377 // copy spawn parms out of the client_t
1378 client = svs.clients + i-1;
1379 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1380 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1387 Returns a color vector indicating the lighting at the requested point.
1389 (Internal Operation note: actually measures the light beneath the point, just like
1390 the model lighting on the client)
1395 static void VM_SV_getlight (void)
1397 vec3_t ambientcolor, diffusecolor, diffusenormal;
1399 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1400 p = PRVM_G_VECTOR(OFS_PARM0);
1401 VectorClear(ambientcolor);
1402 VectorClear(diffusecolor);
1403 VectorClear(diffusenormal);
1404 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1405 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1406 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1411 unsigned char type; // 1/2/8 or other value if isn't used
1415 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1416 static int vm_customstats_last;
1418 void VM_CustomStats_Clear (void)
1422 Z_Free(vm_customstats);
1423 vm_customstats = NULL;
1424 vm_customstats_last = -1;
1428 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1436 for(i=0; i<vm_customstats_last+1 ;i++)
1438 if(!vm_customstats[i].type)
1440 switch(vm_customstats[i].type)
1442 //string as 16 bytes
1445 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1446 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1447 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1448 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1449 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1451 //float field sent as-is
1453 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1455 //integer value of float field
1457 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1465 // void(float index, float type, .void field) SV_AddStat = #232;
1466 // Set up an auto-sent player stat.
1467 // Client's get thier own fields sent to them. Index may not be less than 32.
1468 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1469 // 1: string (4 stats carrying a total of 16 charactures)
1470 // 2: float (one stat, float converted to an integer for transportation)
1471 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1472 static void VM_SV_AddStat (void)
1477 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1481 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1484 VM_Warning("PF_SV_AddStat: not enough memory\n");
1488 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1489 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1490 off = PRVM_G_INT (OFS_PARM2);
1495 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1498 if(i >= (MAX_CL_STATS-32))
1500 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1503 if(i > (MAX_CL_STATS-32-4) && type == 1)
1505 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1508 vm_customstats[i].type = type;
1509 vm_customstats[i].fieldoffset = off;
1510 if(vm_customstats_last < i)
1511 vm_customstats_last = i;
1518 copies data from one entity to another
1520 copyentity(src, dst)
1523 static void VM_SV_copyentity (void)
1525 prvm_edict_t *in, *out;
1526 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1527 in = PRVM_G_EDICT(OFS_PARM0);
1528 if (in == prog->edicts)
1530 VM_Warning("copyentity: can not read world entity\n");
1533 if (in->priv.server->free)
1535 VM_Warning("copyentity: can not read free entity\n");
1538 out = PRVM_G_EDICT(OFS_PARM1);
1539 if (out == prog->edicts)
1541 VM_Warning("copyentity: can not modify world entity\n");
1544 if (out->priv.server->free)
1546 VM_Warning("copyentity: can not modify free entity\n");
1549 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1550 SV_LinkEdict(out, false);
1558 sets the color of a client and broadcasts the update to all connected clients
1560 setcolor(clientent, value)
1563 static void VM_SV_setcolor (void)
1569 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1570 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1571 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1573 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1575 Con_Print("tried to setcolor a non-client\n");
1579 client = svs.clients + entnum-1;
1582 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1584 client->edict->fields.server->team = (i & 15) + 1;
1587 if (client->old_colors != client->colors)
1589 client->old_colors = client->colors;
1590 // send notification to all clients
1591 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1592 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1593 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1601 effect(origin, modelname, startframe, framecount, framerate)
1604 static void VM_SV_effect (void)
1608 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1609 s = PRVM_G_STRING(OFS_PARM1);
1612 VM_Warning("effect: no model specified\n");
1616 i = SV_ModelIndex(s, 1);
1619 VM_Warning("effect: model not precached\n");
1623 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1625 VM_Warning("effect: framecount < 1\n");
1629 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1631 VM_Warning("effect: framerate < 1\n");
1635 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));
1638 static void VM_SV_te_blood (void)
1640 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1641 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1643 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1644 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1646 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1647 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1648 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1650 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1651 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1652 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1654 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1655 SV_FlushBroadcastMessages();
1658 static void VM_SV_te_bloodshower (void)
1660 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1661 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1663 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1664 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1666 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1667 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1668 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1670 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1671 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1672 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1674 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1676 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1677 SV_FlushBroadcastMessages();
1680 static void VM_SV_te_explosionrgb (void)
1682 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1683 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1684 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1686 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1687 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1688 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1690 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1691 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1692 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1693 SV_FlushBroadcastMessages();
1696 static void VM_SV_te_particlecube (void)
1698 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1699 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1701 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1702 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1704 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1705 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1706 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1708 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1709 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1710 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1712 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1713 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1714 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1716 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1718 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1719 // gravity true/false
1720 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1722 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1723 SV_FlushBroadcastMessages();
1726 static void VM_SV_te_particlerain (void)
1728 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1729 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1731 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1732 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1734 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1735 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1736 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1738 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1739 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1740 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1742 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1743 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1744 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1746 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1748 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1749 SV_FlushBroadcastMessages();
1752 static void VM_SV_te_particlesnow (void)
1754 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1755 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1757 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1758 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1760 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1761 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1762 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1764 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1765 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1766 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1768 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1769 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1770 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1772 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1774 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1775 SV_FlushBroadcastMessages();
1778 static void VM_SV_te_spark (void)
1780 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1781 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1783 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1784 MSG_WriteByte(&sv.datagram, TE_SPARK);
1786 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1787 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1788 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1790 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1791 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1792 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1794 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1795 SV_FlushBroadcastMessages();
1798 static void VM_SV_te_gunshotquad (void)
1800 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1801 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1802 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1804 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1805 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1807 SV_FlushBroadcastMessages();
1810 static void VM_SV_te_spikequad (void)
1812 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1813 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1814 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1816 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1817 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1818 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1819 SV_FlushBroadcastMessages();
1822 static void VM_SV_te_superspikequad (void)
1824 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1825 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1826 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1828 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1830 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1831 SV_FlushBroadcastMessages();
1834 static void VM_SV_te_explosionquad (void)
1836 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
1837 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1838 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1840 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1841 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1842 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1843 SV_FlushBroadcastMessages();
1846 static void VM_SV_te_smallflash (void)
1848 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
1849 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1850 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1852 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1853 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1854 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1855 SV_FlushBroadcastMessages();
1858 static void VM_SV_te_customflash (void)
1860 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
1861 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1863 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1864 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1866 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1868 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1870 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1872 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1874 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1875 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1876 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1877 SV_FlushBroadcastMessages();
1880 static void VM_SV_te_gunshot (void)
1882 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
1883 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1884 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1886 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1887 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1888 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1889 SV_FlushBroadcastMessages();
1892 static void VM_SV_te_spike (void)
1894 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
1895 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1896 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1900 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1901 SV_FlushBroadcastMessages();
1904 static void VM_SV_te_superspike (void)
1906 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
1907 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1908 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1911 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1912 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1913 SV_FlushBroadcastMessages();
1916 static void VM_SV_te_explosion (void)
1918 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
1919 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1920 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1922 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1923 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1924 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1925 SV_FlushBroadcastMessages();
1928 static void VM_SV_te_tarexplosion (void)
1930 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
1931 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1932 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1934 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1936 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1937 SV_FlushBroadcastMessages();
1940 static void VM_SV_te_wizspike (void)
1942 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
1943 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1944 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1948 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1949 SV_FlushBroadcastMessages();
1952 static void VM_SV_te_knightspike (void)
1954 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
1955 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1956 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1961 SV_FlushBroadcastMessages();
1964 static void VM_SV_te_lavasplash (void)
1966 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
1967 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1968 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1970 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1972 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1973 SV_FlushBroadcastMessages();
1976 static void VM_SV_te_teleport (void)
1978 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
1979 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1980 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1983 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1984 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1985 SV_FlushBroadcastMessages();
1988 static void VM_SV_te_explosion2 (void)
1990 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
1991 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1992 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1994 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1995 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1996 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1998 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
1999 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2000 SV_FlushBroadcastMessages();
2003 static void VM_SV_te_lightning1 (void)
2005 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2006 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2007 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2009 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2011 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2012 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2015 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2016 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2017 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2018 SV_FlushBroadcastMessages();
2021 static void VM_SV_te_lightning2 (void)
2023 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2024 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2025 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2027 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2029 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2030 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2031 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2033 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2034 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2035 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2036 SV_FlushBroadcastMessages();
2039 static void VM_SV_te_lightning3 (void)
2041 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2042 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2043 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2045 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2047 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2048 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2049 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2052 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2054 SV_FlushBroadcastMessages();
2057 static void VM_SV_te_beam (void)
2059 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2060 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2061 MSG_WriteByte(&sv.datagram, TE_BEAM);
2063 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2065 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2066 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2067 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2069 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2070 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2071 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2072 SV_FlushBroadcastMessages();
2075 static void VM_SV_te_plasmaburn (void)
2077 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2078 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2079 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2080 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2081 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2082 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2083 SV_FlushBroadcastMessages();
2086 static void VM_SV_te_flamejet (void)
2088 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2089 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2090 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2092 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2093 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2094 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2096 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2097 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2098 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2100 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2101 SV_FlushBroadcastMessages();
2104 void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2107 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2109 bestdist = 1000000000;
2111 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2113 // clip original point to each triangle of the surface and find the
2114 // triangle that is closest
2115 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2116 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2117 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2118 TriangleNormal(v[0], v[1], v[2], facenormal);
2119 VectorNormalize(facenormal);
2120 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2121 VectorMA(p, offsetdist, facenormal, temp);
2122 for (j = 0, k = 2;j < 3;k = j, j++)
2124 VectorSubtract(v[k], v[j], edgenormal);
2125 CrossProduct(edgenormal, facenormal, sidenormal);
2126 VectorNormalize(sidenormal);
2127 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2129 VectorMA(temp, offsetdist, sidenormal, temp);
2131 dist = VectorDistance2(temp, p);
2132 if (bestdist > dist)
2135 VectorCopy(temp, out);
2140 static model_t *getmodel(prvm_edict_t *ed)
2143 if (!ed || ed->priv.server->free)
2145 modelindex = (int)ed->fields.server->modelindex;
2146 if (modelindex < 1 || modelindex >= MAX_MODELS)
2148 return sv.models[modelindex];
2151 static msurface_t *getsurface(model_t *model, int surfacenum)
2153 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2155 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2159 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2160 static void VM_SV_getsurfacenumpoints(void)
2163 msurface_t *surface;
2164 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints);
2165 // return 0 if no such surface
2166 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2168 PRVM_G_FLOAT(OFS_RETURN) = 0;
2172 // note: this (incorrectly) assumes it is a simple polygon
2173 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2175 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2176 static void VM_SV_getsurfacepoint(void)
2180 msurface_t *surface;
2182 VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint);
2183 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2184 ed = PRVM_G_EDICT(OFS_PARM0);
2185 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2187 // note: this (incorrectly) assumes it is a simple polygon
2188 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2189 if (pointnum < 0 || pointnum >= surface->num_vertices)
2191 // FIXME: implement rotation/scaling
2192 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2194 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
2195 // float SPA_POSITION = 0;
2196 // float SPA_S_AXIS = 1;
2197 // float SPA_T_AXIS = 2;
2198 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2199 // float SPA_TEXCOORDS0 = 4;
2200 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2201 // float SPA_LIGHTMAP0_COLOR = 6;
2202 static void VM_SV_getsurfacepointattribute(void)
2206 msurface_t *surface;
2210 VM_SAFEPARMCOUNT(4, VM_SV_getsurfacepoint);
2211 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2212 ed = PRVM_G_EDICT(OFS_PARM0);
2213 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2215 // note: this (incorrectly) assumes it is a simple polygon
2216 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2217 if (pointnum < 0 || pointnum >= surface->num_vertices)
2219 // FIXME: implement rotation/scaling
2220 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
2222 switch( attributetype ) {
2223 // float SPA_POSITION = 0;
2225 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2227 // float SPA_S_AXIS = 1;
2229 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2231 // float SPA_T_AXIS = 2;
2233 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2235 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2237 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2239 // float SPA_TEXCOORDS0 = 4;
2241 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2242 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
2243 ret[0] = texcoord[0];
2244 ret[1] = texcoord[1];
2248 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2250 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2251 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
2252 ret[0] = texcoord[0];
2253 ret[1] = texcoord[1];
2257 // float SPA_LIGHTMAP0_COLOR = 6;
2259 // ignore alpha for now..
2260 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2263 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2267 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2268 static void VM_SV_getsurfacenormal(void)
2271 msurface_t *surface;
2273 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal);
2274 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2275 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2277 // FIXME: implement rotation/scaling
2278 // note: this (incorrectly) assumes it is a simple polygon
2279 // note: this only returns the first triangle, so it doesn't work very
2280 // well for curved surfaces or arbitrary meshes
2281 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);
2282 VectorNormalize(normal);
2283 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2285 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2286 static void VM_SV_getsurfacetexture(void)
2289 msurface_t *surface;
2290 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture);
2291 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2292 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2294 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2296 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2297 static void VM_SV_getsurfacenearpoint(void)
2299 int surfacenum, best;
2301 vec_t dist, bestdist;
2304 msurface_t *surface;
2306 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint);
2307 PRVM_G_FLOAT(OFS_RETURN) = -1;
2308 ed = PRVM_G_EDICT(OFS_PARM0);
2309 point = PRVM_G_VECTOR(OFS_PARM1);
2311 if (!ed || ed->priv.server->free)
2313 model = getmodel(ed);
2314 if (!model || !model->num_surfaces)
2317 // FIXME: implement rotation/scaling
2318 VectorSubtract(point, ed->fields.server->origin, p);
2320 bestdist = 1000000000;
2321 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2323 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2324 // first see if the nearest point on the surface's box is closer than the previous match
2325 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2326 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2327 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2328 dist = VectorLength2(clipped);
2329 if (dist < bestdist)
2331 // it is, check the nearest point on the actual geometry
2332 clippointtosurface(model, surface, p, clipped);
2333 VectorSubtract(clipped, p, clipped);
2334 dist += VectorLength2(clipped);
2335 if (dist < bestdist)
2337 // that's closer too, store it as the best match
2343 PRVM_G_FLOAT(OFS_RETURN) = best;
2345 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2346 static void VM_SV_getsurfaceclippedpoint(void)
2350 msurface_t *surface;
2352 VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint);
2353 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2354 ed = PRVM_G_EDICT(OFS_PARM0);
2355 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2357 // FIXME: implement rotation/scaling
2358 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2359 clippointtosurface(model, surface, p, out);
2360 // FIXME: implement rotation/scaling
2361 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2364 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2365 //this function originally written by KrimZon, made shorter by LordHavoc
2366 static void VM_SV_clientcommand (void)
2368 client_t *temp_client;
2370 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2372 //find client for this entity
2373 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2374 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2376 Con_Print("PF_clientcommand: entity is not a client\n");
2380 temp_client = host_client;
2381 host_client = svs.clients + i;
2382 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2383 host_client = temp_client;
2386 //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)
2387 static void VM_SV_setattachment (void)
2389 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2390 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2391 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2395 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2397 if (e == prog->edicts)
2399 VM_Warning("setattachment: can not modify world entity\n");
2402 if (e->priv.server->free)
2404 VM_Warning("setattachment: can not modify free entity\n");
2408 if (tagentity == NULL)
2409 tagentity = prog->edicts;
2411 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2413 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2415 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2418 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2420 modelindex = (int)tagentity->fields.server->modelindex;
2421 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2423 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2425 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);
2428 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));
2432 /////////////////////////////////////////
2433 // DP_MD3_TAGINFO extension coded by VorteX
2435 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2440 i = (int)e->fields.server->modelindex;
2441 if (i < 1 || i >= MAX_MODELS)
2443 model = sv.models[i];
2445 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2448 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2450 float scale = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale)->_float;
2454 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);
2456 Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2], -ent->fields.server->angles[0], ent->fields.server->angles[1], ent->fields.server->angles[2], scale * cl_viewmodel_scale.value);
2459 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2465 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2466 && (model = sv.models[(int)ent->fields.server->modelindex])
2467 && model->animscenes)
2469 // if model has wrong frame, engine automatically switches to model first frame
2470 frame = (int)ent->fields.server->frame;
2471 if (frame < 0 || frame >= model->numframes)
2473 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2475 *out = identitymatrix;
2479 // Warnings/errors code:
2480 // 0 - normal (everything all-right)
2483 // 3 - null or non-precached model
2484 // 4 - no tags with requested index
2485 // 5 - runaway loop at attachment chain
2486 extern cvar_t cl_bob;
2487 extern cvar_t cl_bobcycle;
2488 extern cvar_t cl_bobup;
2489 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2493 int modelindex, attachloop;
2494 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2497 *out = identitymatrix; // warnings and errors return identical matrix
2499 if (ent == prog->edicts)
2501 if (ent->priv.server->free)
2504 modelindex = (int)ent->fields.server->modelindex;
2505 if (modelindex <= 0 || modelindex > MAX_MODELS)
2508 model = sv.models[modelindex];
2510 tagmatrix = identitymatrix;
2511 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2515 if (attachloop >= 256) // prevent runaway looping
2517 // apply transformation by child's tagindex on parent entity and then
2518 // by parent entity itself
2519 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2520 if (ret && attachloop == 0)
2522 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2523 SV_GetEntityMatrix(ent, &entitymatrix, false);
2524 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2525 // next iteration we process the parent entity
2526 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2528 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2529 ent = PRVM_EDICT_NUM(val->edict);
2536 // RENDER_VIEWMODEL magic
2537 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2539 Matrix4x4_Copy(&tagmatrix, out);
2540 ent = PRVM_EDICT_NUM(val->edict);
2542 SV_GetEntityMatrix(ent, &entitymatrix, true);
2543 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2546 // Cl_bob, ported from rendering code
2547 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2550 // LordHavoc: this code is *weird*, but not replacable (I think it
2551 // should be done in QC on the server, but oh well, quake is quake)
2552 // LordHavoc: figured out bobup: the time at which the sin is at 180
2553 // degrees (which allows lengthening or squishing the peak or valley)
2554 cycle = sv.time/cl_bobcycle.value;
2555 cycle -= (int)cycle;
2556 if (cycle < cl_bobup.value)
2557 cycle = sin(M_PI * cycle / cl_bobup.value);
2559 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2560 // bob is proportional to velocity in the xy plane
2561 // (don't count Z, or jumping messes it up)
2562 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;
2563 bob = bob*0.3 + bob*0.7*cycle;
2564 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2571 //float(entity ent, string tagname) gettagindex;
2573 static void VM_SV_gettagindex (void)
2576 const char *tag_name;
2577 int modelindex, tag_index;
2579 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2581 ent = PRVM_G_EDICT(OFS_PARM0);
2582 tag_name = PRVM_G_STRING(OFS_PARM1);
2584 if (ent == prog->edicts)
2586 VM_Warning("gettagindex: can't affect world entity\n");
2589 if (ent->priv.server->free)
2591 VM_Warning("gettagindex: can't affect free entity\n");
2595 modelindex = (int)ent->fields.server->modelindex;
2597 if (modelindex <= 0 || modelindex > MAX_MODELS)
2598 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2601 tag_index = SV_GetTagIndex(ent, tag_name);
2603 if(developer.integer >= 100)
2604 Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2606 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2609 //vector(entity ent, float tagindex) gettaginfo;
2610 static void VM_SV_gettaginfo (void)
2614 matrix4x4_t tag_matrix;
2617 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2619 e = PRVM_G_EDICT(OFS_PARM0);
2620 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2622 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2623 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2628 VM_Warning("gettagindex: can't affect world entity\n");
2631 VM_Warning("gettagindex: can't affect free entity\n");
2634 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2637 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2640 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2645 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2646 static void VM_SV_dropclient (void)
2649 client_t *oldhostclient;
2650 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2651 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2652 if (clientnum < 0 || clientnum >= svs.maxclients)
2654 VM_Warning("dropclient: not a client\n");
2657 if (!svs.clients[clientnum].active)
2659 VM_Warning("dropclient: that client slot is not connected\n");
2662 oldhostclient = host_client;
2663 host_client = svs.clients + clientnum;
2664 SV_DropClient(false);
2665 host_client = oldhostclient;
2668 //entity() spawnclient (DP_SV_BOTCLIENT)
2669 static void VM_SV_spawnclient (void)
2673 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2674 prog->xfunction->builtinsprofile += 2;
2676 for (i = 0;i < svs.maxclients;i++)
2678 if (!svs.clients[i].active)
2680 prog->xfunction->builtinsprofile += 100;
2681 SV_ConnectClient (i, NULL);
2682 // this has to be set or else ClientDisconnect won't be called
2683 // we assume the qc will call ClientConnect...
2684 svs.clients[i].clientconnectcalled = true;
2685 ed = PRVM_EDICT_NUM(i + 1);
2689 VM_RETURN_EDICT(ed);
2692 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2693 static void VM_SV_clienttype (void)
2696 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2697 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2698 if (clientnum < 0 || clientnum >= svs.maxclients)
2699 PRVM_G_FLOAT(OFS_RETURN) = 3;
2700 else if (!svs.clients[clientnum].active)
2701 PRVM_G_FLOAT(OFS_RETURN) = 0;
2702 else if (svs.clients[clientnum].netconnection)
2703 PRVM_G_FLOAT(OFS_RETURN) = 1;
2705 PRVM_G_FLOAT(OFS_RETURN) = 2;
2712 string(string key) serverkey
2715 void VM_SV_serverkey(void)
2717 char string[VM_STRINGTEMP_LENGTH];
2718 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2719 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2720 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2723 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2724 static void VM_SV_setmodelindex (void)
2729 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2731 e = PRVM_G_EDICT(OFS_PARM0);
2732 if (e == prog->edicts)
2734 VM_Warning("setmodelindex: can not modify world entity\n");
2737 if (e->priv.server->free)
2739 VM_Warning("setmodelindex: can not modify free entity\n");
2742 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2743 if (i <= 0 || i > MAX_MODELS)
2745 VM_Warning("setmodelindex: invalid modelindex\n");
2748 if (!sv.model_precache[i][0])
2750 VM_Warning("setmodelindex: model not precached\n");
2754 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2755 e->fields.server->modelindex = i;
2761 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2762 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2764 SetMinMaxSize (e, quakemins, quakemaxs, true);
2767 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2770 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2771 static void VM_SV_modelnameforindex (void)
2774 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2776 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2778 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2779 if (i <= 0 || i > MAX_MODELS)
2781 VM_Warning("modelnameforindex: invalid modelindex\n");
2784 if (!sv.model_precache[i][0])
2786 VM_Warning("modelnameforindex: model not precached\n");
2790 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2793 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2794 static void VM_SV_particleeffectnum (void)
2797 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2798 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2801 PRVM_G_FLOAT(OFS_RETURN) = i;
2804 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2805 static void VM_SV_trailparticles (void)
2807 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2809 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2810 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2811 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2812 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2813 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2814 SV_FlushBroadcastMessages();
2817 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2818 static void VM_SV_pointparticles (void)
2820 int effectnum, count;
2822 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2823 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2824 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2825 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2826 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2827 if (count == 1 && !VectorLength2(vel))
2830 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2831 MSG_WriteShort(&sv.datagram, effectnum);
2832 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2836 // 1+2+12+12+2=29 bytes
2837 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2838 MSG_WriteShort(&sv.datagram, effectnum);
2839 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2840 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2841 MSG_WriteShort(&sv.datagram, count);
2844 SV_FlushBroadcastMessages();
2847 prvm_builtin_t vm_sv_builtins[] = {
2848 NULL, // #0 NULL function (not callable) (QUAKE)
2849 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
2850 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
2851 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
2852 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
2853 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
2854 VM_break, // #6 void() break (QUAKE)
2855 VM_random, // #7 float() random (QUAKE)
2856 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
2857 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
2858 VM_error, // #10 void(string e) error (QUAKE)
2859 VM_objerror, // #11 void(string e) objerror (QUAKE)
2860 VM_vlen, // #12 float(vector v) vlen (QUAKE)
2861 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
2862 VM_spawn, // #14 entity() spawn (QUAKE)
2863 VM_remove, // #15 void(entity e) remove (QUAKE)
2864 VM_SV_traceline, // #16 float(vector v1, vector v2, float tryents) traceline (QUAKE)
2865 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
2866 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
2867 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
2868 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
2869 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
2870 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
2871 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
2872 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
2873 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
2874 VM_ftos, // #26 string(float f) ftos (QUAKE)
2875 VM_vtos, // #27 string(vector v) vtos (QUAKE)
2876 VM_coredump, // #28 void() coredump (QUAKE)
2877 VM_traceon, // #29 void() traceon (QUAKE)
2878 VM_traceoff, // #30 void() traceoff (QUAKE)
2879 VM_eprint, // #31 void(entity e) eprint (QUAKE)
2880 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
2881 NULL, // #33 (QUAKE)
2882 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
2883 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
2884 VM_rint, // #36 float(float v) rint (QUAKE)
2885 VM_floor, // #37 float(float v) floor (QUAKE)
2886 VM_ceil, // #38 float(float v) ceil (QUAKE)
2887 NULL, // #39 (QUAKE)
2888 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
2889 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
2890 NULL, // #42 (QUAKE)
2891 VM_fabs, // #43 float(float f) fabs (QUAKE)
2892 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
2893 VM_cvar, // #45 float(string s) cvar (QUAKE)
2894 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
2895 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
2896 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
2897 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
2898 NULL, // #50 (QUAKE)
2899 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
2900 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
2901 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
2902 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
2903 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
2904 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
2905 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
2906 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
2907 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
2908 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
2909 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
2910 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
2911 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
2912 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
2913 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
2914 NULL, // #66 (QUAKE)
2915 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
2916 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
2917 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
2918 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
2919 NULL, // #71 (QUAKE)
2920 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
2921 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
2922 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
2923 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
2924 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
2925 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
2926 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
2927 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
2928 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
2929 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2930 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
2931 NULL, // #83 (QUAKE)
2932 NULL, // #84 (QUAKE)
2933 NULL, // #85 (QUAKE)
2934 NULL, // #86 (QUAKE)
2935 NULL, // #87 (QUAKE)
2936 NULL, // #88 (QUAKE)
2937 NULL, // #89 (QUAKE)
2938 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2939 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2940 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2941 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2942 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2943 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2944 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2945 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2946 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2947 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2948 // FrikaC and Telejano range #100-#199
2959 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2960 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2961 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2962 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2963 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2964 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
2965 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2966 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2967 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2968 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3049 // FTEQW range #200-#299
3068 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3071 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3072 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3073 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3074 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3075 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3076 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3077 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3078 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3079 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3080 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3082 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3150 // CSQC range #300-#399
3151 NULL, // #300 void() clearscene (EXT_CSQC)
3152 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3153 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3154 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3155 NULL, // #304 void() renderscene (EXT_CSQC)
3156 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3157 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3158 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3159 NULL, // #308 void() R_EndPolygon
3161 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3162 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3166 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3167 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3168 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3169 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3170 NULL, // #319 void(string name) freepic (EXT_CSQC)
3171 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3172 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3173 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3174 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3175 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3176 NULL, // #325 void(void) drawresetcliparea
3181 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3182 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3183 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3184 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3185 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3186 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3187 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3188 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3189 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3190 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3191 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3192 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3193 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3194 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3195 NULL, // #344 vector() getmousepos (EXT_CSQC)
3196 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3197 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3198 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3199 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3200 NULL, // #349 float() isdemo (EXT_CSQC)
3201 VM_isserver, // #350 float() isserver (EXT_CSQC)
3202 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3203 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3204 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3205 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3211 NULL, // #360 float() readbyte (EXT_CSQC)
3212 NULL, // #361 float() readchar (EXT_CSQC)
3213 NULL, // #362 float() readshort (EXT_CSQC)
3214 NULL, // #363 float() readlong (EXT_CSQC)
3215 NULL, // #364 float() readcoord (EXT_CSQC)
3216 NULL, // #365 float() readangle (EXT_CSQC)
3217 NULL, // #366 string() readstring (EXT_CSQC)
3218 NULL, // #367 float() readfloat (EXT_CSQC)
3251 // LordHavoc's range #400-#499
3252 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3253 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3254 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3255 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3256 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3257 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3258 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3259 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3260 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)
3261 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3262 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3263 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3264 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3265 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3266 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3267 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3268 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3269 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3270 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3271 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3272 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3273 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3274 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3275 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3276 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3277 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3278 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3279 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3280 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3281 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3282 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3283 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3284 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3285 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3286 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3287 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3288 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3289 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3290 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3291 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3292 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3293 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3294 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3295 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3296 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3297 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3298 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3299 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3300 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3301 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3302 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3303 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3304 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3305 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3306 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3307 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3308 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3309 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3311 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3312 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3313 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3314 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3315 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3316 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3317 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3318 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3319 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3320 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3321 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3323 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3324 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3325 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3326 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3327 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3328 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3329 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3330 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3331 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3332 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3333 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3334 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3335 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3336 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3337 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3338 VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3346 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3347 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3354 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3356 void VM_SV_Cmd_Init(void)
3361 void VM_SV_Cmd_Reset(void)
3363 if(prog->funcoffsets.SV_Shutdown)
3365 func_t s = prog->funcoffsets.SV_Shutdown;
3366 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3367 PRVM_ExecuteProgram(s,"SV_Shutdown() required");