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 "
61 "DP_QC_FINDCHAINFLAGS "
62 "DP_QC_FINDCHAINFLOAT "
70 "DP_QC_MULTIPLETEMPSTRINGS "
72 "DP_QC_SINCOSSQRTPOW "
74 "DP_QC_STRING_CASE_FUNCTIONS "
75 "DP_QC_STRINGBUFFERS "
76 "DP_QC_STRINGCOLORFUNCTIONS "
77 "DP_QC_TOKENIZEBYSEPARATOR "
80 "DP_QC_TRACE_MOVETYPE_HITMODEL "
81 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
82 "DP_QC_UNLIMITEDTEMPSTRINGS "
83 "DP_QC_VECTOANGLES_WITH_ROLL "
84 "DP_QC_VECTORVECTORS "
90 "DP_SND_DIRECTIONLESSATTNNONE "
99 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
100 "DP_SV_DRAWONLYTOCLIENT "
103 "DP_SV_ENTITYCONTENTSTRANSITION "
104 "DP_SV_ONENTITYNOSPAWNFUNCTION "
105 "DP_SV_MODELFLAGS_AS_EFFECTS "
107 "DP_SV_NODRAWTOCLIENT "
109 "DP_SV_PLAYERPHYSICS "
110 "DP_SV_POINTPARTICLES "
112 "DP_SV_PRECACHEANYTIME "
115 "DP_SV_ROTATINGBMODEL "
118 "DP_SV_WRITEUNTERMINATEDSTRING "
122 "DP_TE_EXPLOSIONRGB "
124 "DP_TE_PARTICLECUBE "
125 "DP_TE_PARTICLERAIN "
126 "DP_TE_PARTICLESNOW "
128 "DP_TE_QUADEFFECTS1 "
131 "DP_TE_STANDARDEFFECTBUILTINS "
132 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
135 //"EXT_CSQC " // not ready yet
137 "KRIMZON_SV_PARSECLIENTCOMMAND "
140 "NEXUIZ_PLAYERMODEL "
142 "PRYDON_CLIENTCURSOR "
143 "TENEBRAE_GFX_DLIGHTS "
153 "DP_QC_GETSURFACEPOINTATTRIBUTE "
160 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.
162 setorigin (entity, origin)
165 static void VM_SV_setorigin (void)
170 VM_SAFEPARMCOUNT(2, VM_setorigin);
172 e = PRVM_G_EDICT(OFS_PARM0);
173 if (e == prog->edicts)
175 VM_Warning("setorigin: can not modify world entity\n");
178 if (e->priv.server->free)
180 VM_Warning("setorigin: can not modify free entity\n");
183 org = PRVM_G_VECTOR(OFS_PARM1);
184 VectorCopy (org, e->fields.server->origin);
185 SV_LinkEdict (e, false);
188 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
189 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
193 for (i=0 ; i<3 ; i++)
195 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
197 // set derived values
198 VectorCopy (min, e->fields.server->mins);
199 VectorCopy (max, e->fields.server->maxs);
200 VectorSubtract (max, min, e->fields.server->size);
202 SV_LinkEdict (e, false);
209 the size box is rotated by the current angle
210 LordHavoc: no it isn't...
212 setsize (entity, minvector, maxvector)
215 static void VM_SV_setsize (void)
220 VM_SAFEPARMCOUNT(3, VM_setsize);
222 e = PRVM_G_EDICT(OFS_PARM0);
223 if (e == prog->edicts)
225 VM_Warning("setsize: can not modify world entity\n");
228 if (e->priv.server->free)
230 VM_Warning("setsize: can not modify free entity\n");
233 min = PRVM_G_VECTOR(OFS_PARM1);
234 max = PRVM_G_VECTOR(OFS_PARM2);
235 SetMinMaxSize (e, min, max, false);
243 setmodel(entity, model)
246 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
247 static void VM_SV_setmodel (void)
253 VM_SAFEPARMCOUNT(2, VM_setmodel);
255 e = PRVM_G_EDICT(OFS_PARM0);
256 if (e == prog->edicts)
258 VM_Warning("setmodel: can not modify world entity\n");
261 if (e->priv.server->free)
263 VM_Warning("setmodel: can not modify free entity\n");
266 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
267 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
268 e->fields.server->modelindex = i;
274 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
275 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
277 SetMinMaxSize (e, quakemins, quakemaxs, true);
280 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
287 single print to a specific client
289 sprint(clientent, value)
292 static void VM_SV_sprint (void)
296 char string[VM_STRINGTEMP_LENGTH];
298 VM_VarString(1, string, sizeof(string));
300 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
302 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
303 // LordHavoc: div0 requested that sprintto world operate like print
310 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
312 VM_Warning("tried to centerprint to a non-client\n");
316 client = svs.clients + entnum-1;
317 if (!client->netconnection)
320 MSG_WriteChar(&client->netconnection->message,svc_print);
321 MSG_WriteString(&client->netconnection->message, string);
329 single print to a specific client
331 centerprint(clientent, value)
334 static void VM_SV_centerprint (void)
338 char string[VM_STRINGTEMP_LENGTH];
340 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
342 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
344 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
346 VM_Warning("tried to centerprint to a non-client\n");
350 client = svs.clients + entnum-1;
351 if (!client->netconnection)
354 VM_VarString(1, string, sizeof(string));
355 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
356 MSG_WriteString(&client->netconnection->message, string);
363 particle(origin, color, count)
366 static void VM_SV_particle (void)
372 VM_SAFEPARMCOUNT(4, VM_SV_particle);
374 org = PRVM_G_VECTOR(OFS_PARM0);
375 dir = PRVM_G_VECTOR(OFS_PARM1);
376 color = PRVM_G_FLOAT(OFS_PARM2);
377 count = PRVM_G_FLOAT(OFS_PARM3);
378 SV_StartParticle (org, dir, (int)color, (int)count);
388 static void VM_SV_ambientsound (void)
392 float vol, attenuation;
395 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
397 pos = PRVM_G_VECTOR (OFS_PARM0);
398 samp = PRVM_G_STRING(OFS_PARM1);
399 vol = PRVM_G_FLOAT(OFS_PARM2);
400 attenuation = PRVM_G_FLOAT(OFS_PARM3);
402 // check to see if samp was properly precached
403 soundnum = SV_SoundIndex(samp, 1);
411 // add an svc_spawnambient command to the level signon packet
414 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
416 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
418 MSG_WriteVector(&sv.signon, pos, sv.protocol);
420 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
421 MSG_WriteShort (&sv.signon, soundnum);
423 MSG_WriteByte (&sv.signon, soundnum);
425 MSG_WriteByte (&sv.signon, (int)(vol*255));
426 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
434 Each entity can have eight independant sound sources, like voice,
437 Channel 0 is an auto-allocate channel, the others override anything
438 already running on that entity/channel pair.
440 An attenuation of 0 will play full volume everywhere in the level.
441 Larger attenuations will drop off.
445 static void VM_SV_sound (void)
449 prvm_edict_t *entity;
453 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
455 entity = PRVM_G_EDICT(OFS_PARM0);
456 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
457 sample = PRVM_G_STRING(OFS_PARM2);
458 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
459 attenuation = PRVM_G_FLOAT(OFS_PARM4);
462 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
466 if (volume < 0 || volume > 255)
468 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
472 if (attenuation < 0 || attenuation > 4)
474 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
478 if (channel < 0 || channel > 7)
480 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
484 SV_StartSound (entity, channel, sample, volume, attenuation);
491 Follows the same logic as VM_SV_sound, except instead of
492 an entity, an origin for the sound is provided, and channel
493 is omitted (since no entity is being tracked).
497 static void VM_SV_pointsound(void)
504 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
506 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
507 sample = PRVM_G_STRING(OFS_PARM1);
508 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
509 attenuation = PRVM_G_FLOAT(OFS_PARM3);
511 if (volume < 0 || volume > 255)
513 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
517 if (attenuation < 0 || attenuation > 4)
519 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
523 SV_StartPointSound (org, sample, volume, attenuation);
530 Used for use tracing and shot targeting
531 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
532 if the tryents flag is set.
534 traceline (vector1, vector2, movetype, ignore)
537 static void VM_SV_traceline (void)
544 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
546 prog->xfunction->builtinsprofile += 30;
548 v1 = PRVM_G_VECTOR(OFS_PARM0);
549 v2 = PRVM_G_VECTOR(OFS_PARM1);
550 move = (int)PRVM_G_FLOAT(OFS_PARM2);
551 ent = PRVM_G_EDICT(OFS_PARM3);
553 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]))
554 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));
556 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
558 VM_SetTraceGlobals(&trace);
566 Used for use tracing and shot targeting
567 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
568 if the tryents flag is set.
570 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
573 // LordHavoc: added this for my own use, VERY useful, similar to traceline
574 static void VM_SV_tracebox (void)
576 float *v1, *v2, *m1, *m2;
581 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
583 prog->xfunction->builtinsprofile += 30;
585 v1 = PRVM_G_VECTOR(OFS_PARM0);
586 m1 = PRVM_G_VECTOR(OFS_PARM1);
587 m2 = PRVM_G_VECTOR(OFS_PARM2);
588 v2 = PRVM_G_VECTOR(OFS_PARM3);
589 move = (int)PRVM_G_FLOAT(OFS_PARM4);
590 ent = PRVM_G_EDICT(OFS_PARM5);
592 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]))
593 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));
595 trace = SV_Move (v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
597 VM_SetTraceGlobals(&trace);
600 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
605 vec3_t original_origin;
606 vec3_t original_velocity;
607 vec3_t original_angles;
608 vec3_t original_avelocity;
612 VectorCopy(tossent->fields.server->origin , original_origin );
613 VectorCopy(tossent->fields.server->velocity , original_velocity );
614 VectorCopy(tossent->fields.server->angles , original_angles );
615 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
617 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
618 if (val != NULL && val->_float != 0)
619 gravity = val->_float;
622 gravity *= sv_gravity.value * 0.05;
624 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
626 SV_CheckVelocity (tossent);
627 tossent->fields.server->velocity[2] -= gravity;
628 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
629 VectorScale (tossent->fields.server->velocity, 0.05, move);
630 VectorAdd (tossent->fields.server->origin, move, end);
631 trace = SV_Move (tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
632 VectorCopy (trace.endpos, tossent->fields.server->origin);
634 if (trace.fraction < 1)
638 VectorCopy(original_origin , tossent->fields.server->origin );
639 VectorCopy(original_velocity , tossent->fields.server->velocity );
640 VectorCopy(original_angles , tossent->fields.server->angles );
641 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
646 static void VM_SV_tracetoss (void)
650 prvm_edict_t *ignore;
652 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
654 prog->xfunction->builtinsprofile += 600;
656 ent = PRVM_G_EDICT(OFS_PARM0);
657 if (ent == prog->edicts)
659 VM_Warning("tracetoss: can not use world entity\n");
662 ignore = PRVM_G_EDICT(OFS_PARM1);
664 trace = SV_Trace_Toss (ent, ignore);
666 VM_SetTraceGlobals(&trace);
669 //============================================================================
671 static int checkpvsbytes;
672 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
674 static int VM_SV_newcheckclient (int check)
680 // cycle to the next one
682 check = bound(1, check, svs.maxclients);
683 if (check == svs.maxclients)
691 prog->xfunction->builtinsprofile++;
693 if (i == svs.maxclients+1)
695 // look up the client's edict
696 ent = PRVM_EDICT_NUM(i);
697 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
698 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
700 // found a valid client (possibly the same one again)
704 // get the PVS for the entity
705 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
707 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
708 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
717 Returns a client (or object that has a client enemy) that would be a
720 If there is more than one valid option, they are cycled each frame
722 If (self.origin + self.viewofs) is not in the PVS of the current target,
723 it is not returned at all.
728 int c_invis, c_notvis;
729 static void VM_SV_checkclient (void)
731 prvm_edict_t *ent, *self;
734 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
736 // find a new check if on a new frame
737 if (sv.time - sv.lastchecktime >= 0.1)
739 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
740 sv.lastchecktime = sv.time;
743 // return check if it might be visible
744 ent = PRVM_EDICT_NUM(sv.lastcheck);
745 if (ent->priv.server->free || ent->fields.server->health <= 0)
747 VM_RETURN_EDICT(prog->edicts);
751 // if current entity can't possibly see the check entity, return 0
752 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
753 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
754 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
757 VM_RETURN_EDICT(prog->edicts);
761 // might be able to see it
763 VM_RETURN_EDICT(ent);
766 //============================================================================
773 Sends text over to the client's execution buffer
775 stuffcmd (clientent, value, ...)
778 static void VM_SV_stuffcmd (void)
782 char string[VM_STRINGTEMP_LENGTH];
784 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
786 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
787 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
789 VM_Warning("Can't stuffcmd to a non-client\n");
793 VM_VarString(1, string, sizeof(string));
796 host_client = svs.clients + entnum-1;
797 Host_ClientCommands ("%s", string);
805 Returns a chain of entities that have origins within a spherical area
807 findradius (origin, radius)
810 static void VM_SV_findradius (void)
812 prvm_edict_t *ent, *chain;
813 vec_t radius, radius2;
814 vec3_t org, eorg, mins, maxs;
817 prvm_edict_t *touchedicts[MAX_EDICTS];
819 VM_SAFEPARMCOUNT(2, VM_SV_findradius);
821 chain = (prvm_edict_t *)prog->edicts;
823 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
824 radius = PRVM_G_FLOAT(OFS_PARM1);
825 radius2 = radius * radius;
827 mins[0] = org[0] - (radius + 1);
828 mins[1] = org[1] - (radius + 1);
829 mins[2] = org[2] - (radius + 1);
830 maxs[0] = org[0] + (radius + 1);
831 maxs[1] = org[1] + (radius + 1);
832 maxs[2] = org[2] + (radius + 1);
833 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
834 if (numtouchedicts > MAX_EDICTS)
836 // this never happens
837 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
838 numtouchedicts = MAX_EDICTS;
840 for (i = 0;i < numtouchedicts;i++)
842 ent = touchedicts[i];
843 prog->xfunction->builtinsprofile++;
844 // Quake did not return non-solid entities but darkplaces does
845 // (note: this is the reason you can't blow up fallen zombies)
846 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
848 // LordHavoc: compare against bounding box rather than center so it
849 // doesn't miss large objects, and use DotProduct instead of Length
850 // for a major speedup
851 VectorSubtract(org, ent->fields.server->origin, eorg);
852 if (sv_gameplayfix_findradiusdistancetobox.integer)
854 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
855 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
856 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
859 VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
860 if (DotProduct(eorg, eorg) < radius2)
862 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
867 VM_RETURN_EDICT(chain);
870 static void VM_SV_precache_sound (void)
872 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
873 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
876 static void VM_SV_precache_model (void)
878 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
879 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
880 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
887 float(float yaw, float dist[, settrace]) walkmove
890 static void VM_SV_walkmove (void)
899 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
901 // assume failure if it returns early
902 PRVM_G_FLOAT(OFS_RETURN) = 0;
904 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
905 if (ent == prog->edicts)
907 VM_Warning("walkmove: can not modify world entity\n");
910 if (ent->priv.server->free)
912 VM_Warning("walkmove: can not modify free entity\n");
915 yaw = PRVM_G_FLOAT(OFS_PARM0);
916 dist = PRVM_G_FLOAT(OFS_PARM1);
917 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
919 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
922 yaw = yaw*M_PI*2 / 360;
924 move[0] = cos(yaw)*dist;
925 move[1] = sin(yaw)*dist;
928 // save program state, because SV_movestep may call other progs
929 oldf = prog->xfunction;
930 oldself = prog->globals.server->self;
932 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
935 // restore program state
936 prog->xfunction = oldf;
937 prog->globals.server->self = oldself;
947 static void VM_SV_droptofloor (void)
953 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
955 // assume failure if it returns early
956 PRVM_G_FLOAT(OFS_RETURN) = 0;
958 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
959 if (ent == prog->edicts)
961 VM_Warning("droptofloor: can not modify world entity\n");
964 if (ent->priv.server->free)
966 VM_Warning("droptofloor: can not modify free entity\n");
970 VectorCopy (ent->fields.server->origin, end);
973 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
974 SV_UnstickEntity(ent);
976 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
977 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
980 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]);
981 VectorAdd(ent->fields.server->origin, offset, org);
982 trace = SV_Move (org, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
983 VectorSubtract(trace.endpos, offset, trace.endpos);
984 if (trace.startsolid)
986 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]);
987 SV_UnstickEntity(ent);
988 SV_LinkEdict (ent, false);
989 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
990 ent->fields.server->groundentity = 0;
991 PRVM_G_FLOAT(OFS_RETURN) = 1;
993 else if (trace.fraction < 1)
995 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]);
996 VectorCopy (trace.endpos, ent->fields.server->origin);
997 SV_UnstickEntity(ent);
998 SV_LinkEdict (ent, false);
999 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1000 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1001 PRVM_G_FLOAT(OFS_RETURN) = 1;
1002 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1003 ent->priv.server->suspendedinairflag = true;
1008 if (trace.fraction != 1)
1010 if (trace.fraction < 1)
1011 VectorCopy (trace.endpos, ent->fields.server->origin);
1012 SV_LinkEdict (ent, false);
1013 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1014 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1015 PRVM_G_FLOAT(OFS_RETURN) = 1;
1016 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1017 ent->priv.server->suspendedinairflag = true;
1026 void(float style, string value) lightstyle
1029 static void VM_SV_lightstyle (void)
1036 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1038 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1039 val = PRVM_G_STRING(OFS_PARM1);
1041 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1042 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1045 // change the string in sv
1046 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1048 // send message to all clients on this server
1049 if (sv.state != ss_active)
1052 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1054 if (client->active && client->netconnection)
1056 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1057 MSG_WriteChar (&client->netconnection->message,style);
1058 MSG_WriteString (&client->netconnection->message, val);
1068 static void VM_SV_checkbottom (void)
1070 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1071 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1079 static void VM_SV_pointcontents (void)
1081 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1082 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1089 Pick a vector for the player to shoot along
1090 vector aim(entity, missilespeed)
1093 static void VM_SV_aim (void)
1095 prvm_edict_t *ent, *check, *bestent;
1096 vec3_t start, dir, end, bestdir;
1099 float dist, bestdist;
1102 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1104 // assume failure if it returns early
1105 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1106 // if sv_aim is so high it can't possibly accept anything, skip out early
1107 if (sv_aim.value >= 1)
1110 ent = PRVM_G_EDICT(OFS_PARM0);
1111 if (ent == prog->edicts)
1113 VM_Warning("aim: can not use world entity\n");
1116 if (ent->priv.server->free)
1118 VM_Warning("aim: can not use free entity\n");
1121 speed = PRVM_G_FLOAT(OFS_PARM1);
1123 VectorCopy (ent->fields.server->origin, start);
1126 // try sending a trace straight
1127 VectorCopy (prog->globals.server->v_forward, dir);
1128 VectorMA (start, 2048, dir, end);
1129 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1130 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1131 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1133 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1138 // try all possible entities
1139 VectorCopy (dir, bestdir);
1140 bestdist = sv_aim.value;
1143 check = PRVM_NEXT_EDICT(prog->edicts);
1144 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1146 prog->xfunction->builtinsprofile++;
1147 if (check->fields.server->takedamage != DAMAGE_AIM)
1151 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1152 continue; // don't aim at teammate
1153 for (j=0 ; j<3 ; j++)
1154 end[j] = check->fields.server->origin[j]
1155 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1156 VectorSubtract (end, start, dir);
1157 VectorNormalize (dir);
1158 dist = DotProduct (dir, prog->globals.server->v_forward);
1159 if (dist < bestdist)
1160 continue; // to far to turn
1161 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1162 if (tr.ent == check)
1163 { // can shoot at this one
1171 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1172 dist = DotProduct (dir, prog->globals.server->v_forward);
1173 VectorScale (prog->globals.server->v_forward, dist, end);
1175 VectorNormalize (end);
1176 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1180 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1185 ===============================================================================
1189 ===============================================================================
1192 #define MSG_BROADCAST 0 // unreliable to all
1193 #define MSG_ONE 1 // reliable to one (msg_entity)
1194 #define MSG_ALL 2 // reliable to all
1195 #define MSG_INIT 3 // write to the init string
1196 #define MSG_ENTITY 5
1198 sizebuf_t *WriteDest (void)
1204 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1208 return &sv.datagram;
1211 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1212 entnum = PRVM_NUM_FOR_EDICT(ent);
1213 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1215 VM_Warning ("WriteDest: tried to write to non-client\n");
1216 return &sv.reliable_datagram;
1219 return &svs.clients[entnum-1].netconnection->message;
1222 VM_Warning ("WriteDest: bad destination\n");
1224 return &sv.reliable_datagram;
1230 return sv.writeentitiestoclient_msg;
1236 static void VM_SV_WriteByte (void)
1238 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1239 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1242 static void VM_SV_WriteChar (void)
1244 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1245 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1248 static void VM_SV_WriteShort (void)
1250 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1251 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1254 static void VM_SV_WriteLong (void)
1256 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1257 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1260 static void VM_SV_WriteAngle (void)
1262 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1263 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1266 static void VM_SV_WriteCoord (void)
1268 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1269 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1272 static void VM_SV_WriteString (void)
1274 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1275 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1278 static void VM_SV_WriteUnterminatedString (void)
1280 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1281 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1285 static void VM_SV_WriteEntity (void)
1287 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1288 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1291 //////////////////////////////////////////////////////////
1293 static void VM_SV_makestatic (void)
1298 // allow 0 parameters due to an id1 qc bug in which this function is used
1299 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1300 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1302 if (prog->argc >= 1)
1303 ent = PRVM_G_EDICT(OFS_PARM0);
1305 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1306 if (ent == prog->edicts)
1308 VM_Warning("makestatic: can not modify world entity\n");
1311 if (ent->priv.server->free)
1313 VM_Warning("makestatic: can not modify free entity\n");
1318 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1323 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1324 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1325 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1327 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1329 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1330 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1331 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1335 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1336 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1337 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1340 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1341 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1342 for (i=0 ; i<3 ; i++)
1344 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1345 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1348 // throw the entity away now
1352 //=============================================================================
1359 static void VM_SV_setspawnparms (void)
1365 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1367 ent = PRVM_G_EDICT(OFS_PARM0);
1368 i = PRVM_NUM_FOR_EDICT(ent);
1369 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1371 Con_Print("tried to setspawnparms on a non-client\n");
1375 // copy spawn parms out of the client_t
1376 client = svs.clients + i-1;
1377 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1378 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1385 Returns a color vector indicating the lighting at the requested point.
1387 (Internal Operation note: actually measures the light beneath the point, just like
1388 the model lighting on the client)
1393 static void VM_SV_getlight (void)
1395 vec3_t ambientcolor, diffusecolor, diffusenormal;
1397 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1398 p = PRVM_G_VECTOR(OFS_PARM0);
1399 VectorClear(ambientcolor);
1400 VectorClear(diffusecolor);
1401 VectorClear(diffusenormal);
1402 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1403 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1404 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1409 unsigned char type; // 1/2/8 or other value if isn't used
1413 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1414 static int vm_customstats_last;
1416 void VM_CustomStats_Clear (void)
1420 Z_Free(vm_customstats);
1421 vm_customstats = NULL;
1422 vm_customstats_last = -1;
1426 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1434 for(i=0; i<vm_customstats_last+1 ;i++)
1436 if(!vm_customstats[i].type)
1438 switch(vm_customstats[i].type)
1440 //string as 16 bytes
1443 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1444 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1445 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1446 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1447 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1449 //float field sent as-is
1451 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1453 //integer value of float field
1455 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1463 // void(float index, float type, .void field) SV_AddStat = #232;
1464 // Set up an auto-sent player stat.
1465 // Client's get thier own fields sent to them. Index may not be less than 32.
1466 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1467 // 1: string (4 stats carrying a total of 16 charactures)
1468 // 2: float (one stat, float converted to an integer for transportation)
1469 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1470 static void VM_SV_AddStat (void)
1475 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1479 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1482 VM_Warning("PF_SV_AddStat: not enough memory\n");
1486 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1487 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1488 off = PRVM_G_INT (OFS_PARM2);
1493 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1496 if(i >= (MAX_CL_STATS-32))
1498 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1501 if(i > (MAX_CL_STATS-32-4) && type == 1)
1503 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1506 vm_customstats[i].type = type;
1507 vm_customstats[i].fieldoffset = off;
1508 if(vm_customstats_last < i)
1509 vm_customstats_last = i;
1516 copies data from one entity to another
1518 copyentity(src, dst)
1521 static void VM_SV_copyentity (void)
1523 prvm_edict_t *in, *out;
1524 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1525 in = PRVM_G_EDICT(OFS_PARM0);
1526 if (in == prog->edicts)
1528 VM_Warning("copyentity: can not read world entity\n");
1531 if (in->priv.server->free)
1533 VM_Warning("copyentity: can not read free entity\n");
1536 out = PRVM_G_EDICT(OFS_PARM1);
1537 if (out == prog->edicts)
1539 VM_Warning("copyentity: can not modify world entity\n");
1542 if (out->priv.server->free)
1544 VM_Warning("copyentity: can not modify free entity\n");
1547 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1548 SV_LinkEdict(out, false);
1556 sets the color of a client and broadcasts the update to all connected clients
1558 setcolor(clientent, value)
1561 static void VM_SV_setcolor (void)
1567 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1568 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1569 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1571 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1573 Con_Print("tried to setcolor a non-client\n");
1577 client = svs.clients + entnum-1;
1580 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1582 client->edict->fields.server->team = (i & 15) + 1;
1585 if (client->old_colors != client->colors)
1587 client->old_colors = client->colors;
1588 // send notification to all clients
1589 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1590 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1591 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1599 effect(origin, modelname, startframe, framecount, framerate)
1602 static void VM_SV_effect (void)
1606 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1607 s = PRVM_G_STRING(OFS_PARM1);
1610 VM_Warning("effect: no model specified\n");
1614 i = SV_ModelIndex(s, 1);
1617 VM_Warning("effect: model not precached\n");
1621 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1623 VM_Warning("effect: framecount < 1\n");
1627 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1629 VM_Warning("effect: framerate < 1\n");
1633 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));
1636 static void VM_SV_te_blood (void)
1638 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1639 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1641 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1642 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1644 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1645 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1646 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1648 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1649 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1650 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1652 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1653 SV_FlushBroadcastMessages();
1656 static void VM_SV_te_bloodshower (void)
1658 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1659 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1661 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1662 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1664 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1665 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1666 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1668 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1669 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1670 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1672 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1674 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1675 SV_FlushBroadcastMessages();
1678 static void VM_SV_te_explosionrgb (void)
1680 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1681 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1682 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1684 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1685 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1686 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1688 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1689 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1690 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1691 SV_FlushBroadcastMessages();
1694 static void VM_SV_te_particlecube (void)
1696 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1697 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1699 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1700 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1702 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1703 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1704 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1706 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1707 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1708 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1710 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1711 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1712 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1714 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1716 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1717 // gravity true/false
1718 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1720 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1721 SV_FlushBroadcastMessages();
1724 static void VM_SV_te_particlerain (void)
1726 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1727 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1729 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1730 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1732 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1733 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1734 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1736 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1737 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1738 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1740 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1741 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1742 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1744 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1746 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1747 SV_FlushBroadcastMessages();
1750 static void VM_SV_te_particlesnow (void)
1752 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1753 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1755 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1756 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1758 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1759 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1760 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1762 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1763 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1764 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1766 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1767 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1768 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1770 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1772 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1773 SV_FlushBroadcastMessages();
1776 static void VM_SV_te_spark (void)
1778 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1779 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1781 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1782 MSG_WriteByte(&sv.datagram, TE_SPARK);
1784 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1785 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1786 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1788 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1789 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1790 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1792 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1793 SV_FlushBroadcastMessages();
1796 static void VM_SV_te_gunshotquad (void)
1798 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1799 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1800 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1802 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1803 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1804 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1805 SV_FlushBroadcastMessages();
1808 static void VM_SV_te_spikequad (void)
1810 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1811 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1812 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1814 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1815 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1816 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1817 SV_FlushBroadcastMessages();
1820 static void VM_SV_te_superspikequad (void)
1822 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1823 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1824 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1826 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1827 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1828 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1829 SV_FlushBroadcastMessages();
1832 static void VM_SV_te_explosionquad (void)
1834 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
1835 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1836 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1838 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1839 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1840 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1841 SV_FlushBroadcastMessages();
1844 static void VM_SV_te_smallflash (void)
1846 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
1847 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1848 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1850 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1851 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1852 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1853 SV_FlushBroadcastMessages();
1856 static void VM_SV_te_customflash (void)
1858 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
1859 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1861 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1862 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1864 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1865 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1866 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1868 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1870 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1872 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1873 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1874 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1875 SV_FlushBroadcastMessages();
1878 static void VM_SV_te_gunshot (void)
1880 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
1881 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1882 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1884 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1885 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1886 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1887 SV_FlushBroadcastMessages();
1890 static void VM_SV_te_spike (void)
1892 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
1893 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1894 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1896 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1899 SV_FlushBroadcastMessages();
1902 static void VM_SV_te_superspike (void)
1904 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
1905 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1906 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1911 SV_FlushBroadcastMessages();
1914 static void VM_SV_te_explosion (void)
1916 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
1917 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1918 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1920 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1921 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1922 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1923 SV_FlushBroadcastMessages();
1926 static void VM_SV_te_tarexplosion (void)
1928 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
1929 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1930 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1934 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1935 SV_FlushBroadcastMessages();
1938 static void VM_SV_te_wizspike (void)
1940 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
1941 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1942 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1944 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1945 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1947 SV_FlushBroadcastMessages();
1950 static void VM_SV_te_knightspike (void)
1952 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
1953 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1954 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1959 SV_FlushBroadcastMessages();
1962 static void VM_SV_te_lavasplash (void)
1964 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
1965 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1966 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1970 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1971 SV_FlushBroadcastMessages();
1974 static void VM_SV_te_teleport (void)
1976 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
1977 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1978 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1980 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1983 SV_FlushBroadcastMessages();
1986 static void VM_SV_te_explosion2 (void)
1988 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
1989 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1990 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1992 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1993 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1994 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1996 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
1997 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
1998 SV_FlushBroadcastMessages();
2001 static void VM_SV_te_lightning1 (void)
2003 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2004 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2005 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2007 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2009 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2010 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2011 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2014 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2015 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2016 SV_FlushBroadcastMessages();
2019 static void VM_SV_te_lightning2 (void)
2021 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2022 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2023 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2025 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2028 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2029 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2031 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2032 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2033 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2034 SV_FlushBroadcastMessages();
2037 static void VM_SV_te_lightning3 (void)
2039 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2040 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2041 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2043 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2045 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2046 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2047 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2049 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2050 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2052 SV_FlushBroadcastMessages();
2055 static void VM_SV_te_beam (void)
2057 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2058 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2059 MSG_WriteByte(&sv.datagram, TE_BEAM);
2061 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2063 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2064 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2065 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2067 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2068 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2069 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2070 SV_FlushBroadcastMessages();
2073 static void VM_SV_te_plasmaburn (void)
2075 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2076 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2077 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2078 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2079 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2080 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2081 SV_FlushBroadcastMessages();
2084 static void VM_SV_te_flamejet (void)
2086 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2087 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2088 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2090 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2091 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2092 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2094 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2095 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2096 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2098 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2099 SV_FlushBroadcastMessages();
2102 void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2105 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2107 bestdist = 1000000000;
2109 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2111 // clip original point to each triangle of the surface and find the
2112 // triangle that is closest
2113 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2114 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2115 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2116 TriangleNormal(v[0], v[1], v[2], facenormal);
2117 VectorNormalize(facenormal);
2118 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2119 VectorMA(p, offsetdist, facenormal, temp);
2120 for (j = 0, k = 2;j < 3;k = j, j++)
2122 VectorSubtract(v[k], v[j], edgenormal);
2123 CrossProduct(edgenormal, facenormal, sidenormal);
2124 VectorNormalize(sidenormal);
2125 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2127 VectorMA(temp, offsetdist, sidenormal, temp);
2129 dist = VectorDistance2(temp, p);
2130 if (bestdist > dist)
2133 VectorCopy(temp, out);
2138 static model_t *getmodel(prvm_edict_t *ed)
2141 if (!ed || ed->priv.server->free)
2143 modelindex = (int)ed->fields.server->modelindex;
2144 if (modelindex < 1 || modelindex >= MAX_MODELS)
2146 return sv.models[modelindex];
2149 static msurface_t *getsurface(model_t *model, int surfacenum)
2151 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2153 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2157 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2158 static void VM_SV_getsurfacenumpoints(void)
2161 msurface_t *surface;
2162 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints);
2163 // return 0 if no such surface
2164 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2166 PRVM_G_FLOAT(OFS_RETURN) = 0;
2170 // note: this (incorrectly) assumes it is a simple polygon
2171 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2173 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2174 static void VM_SV_getsurfacepoint(void)
2178 msurface_t *surface;
2180 VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint);
2181 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2182 ed = PRVM_G_EDICT(OFS_PARM0);
2183 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2185 // note: this (incorrectly) assumes it is a simple polygon
2186 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2187 if (pointnum < 0 || pointnum >= surface->num_vertices)
2189 // FIXME: implement rotation/scaling
2190 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2192 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
2193 // float SPA_POSITION = 0;
2194 // float SPA_S_AXIS = 1;
2195 // float SPA_T_AXIS = 2;
2196 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2197 // float SPA_TEXCOORDS0 = 4;
2198 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2199 // float SPA_LIGHTMAP0_COLOR = 6;
2200 static void VM_SV_getsurfacepointattribute(void)
2204 msurface_t *surface;
2208 VM_SAFEPARMCOUNT(4, VM_SV_getsurfacepoint);
2209 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2210 ed = PRVM_G_EDICT(OFS_PARM0);
2211 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2213 // note: this (incorrectly) assumes it is a simple polygon
2214 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2215 if (pointnum < 0 || pointnum >= surface->num_vertices)
2217 // FIXME: implement rotation/scaling
2218 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
2220 switch( attributetype ) {
2221 // float SPA_POSITION = 0;
2223 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2225 // float SPA_S_AXIS = 1;
2227 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2229 // float SPA_T_AXIS = 2;
2231 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2233 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2235 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2237 // float SPA_TEXCOORDS0 = 4;
2239 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2240 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
2241 ret[0] = texcoord[0];
2242 ret[1] = texcoord[1];
2246 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2248 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2249 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
2250 ret[0] = texcoord[0];
2251 ret[1] = texcoord[1];
2255 // float SPA_LIGHTMAP0_COLOR = 6;
2257 // ignore alpha for now..
2258 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2261 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2265 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2266 static void VM_SV_getsurfacenormal(void)
2269 msurface_t *surface;
2271 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal);
2272 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2273 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2275 // FIXME: implement rotation/scaling
2276 // note: this (incorrectly) assumes it is a simple polygon
2277 // note: this only returns the first triangle, so it doesn't work very
2278 // well for curved surfaces or arbitrary meshes
2279 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);
2280 VectorNormalize(normal);
2281 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2283 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2284 static void VM_SV_getsurfacetexture(void)
2287 msurface_t *surface;
2288 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture);
2289 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2290 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2292 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2294 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2295 static void VM_SV_getsurfacenearpoint(void)
2297 int surfacenum, best;
2299 vec_t dist, bestdist;
2302 msurface_t *surface;
2304 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint);
2305 PRVM_G_FLOAT(OFS_RETURN) = -1;
2306 ed = PRVM_G_EDICT(OFS_PARM0);
2307 point = PRVM_G_VECTOR(OFS_PARM1);
2309 if (!ed || ed->priv.server->free)
2311 model = getmodel(ed);
2312 if (!model || !model->num_surfaces)
2315 // FIXME: implement rotation/scaling
2316 VectorSubtract(point, ed->fields.server->origin, p);
2318 bestdist = 1000000000;
2319 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2321 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2322 // first see if the nearest point on the surface's box is closer than the previous match
2323 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2324 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2325 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2326 dist = VectorLength2(clipped);
2327 if (dist < bestdist)
2329 // it is, check the nearest point on the actual geometry
2330 clippointtosurface(model, surface, p, clipped);
2331 VectorSubtract(clipped, p, clipped);
2332 dist += VectorLength2(clipped);
2333 if (dist < bestdist)
2335 // that's closer too, store it as the best match
2341 PRVM_G_FLOAT(OFS_RETURN) = best;
2343 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2344 static void VM_SV_getsurfaceclippedpoint(void)
2348 msurface_t *surface;
2350 VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint);
2351 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2352 ed = PRVM_G_EDICT(OFS_PARM0);
2353 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2355 // FIXME: implement rotation/scaling
2356 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2357 clippointtosurface(model, surface, p, out);
2358 // FIXME: implement rotation/scaling
2359 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2362 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2363 //this function originally written by KrimZon, made shorter by LordHavoc
2364 static void VM_SV_clientcommand (void)
2366 client_t *temp_client;
2368 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2370 //find client for this entity
2371 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2372 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2374 Con_Print("PF_clientcommand: entity is not a client\n");
2378 temp_client = host_client;
2379 host_client = svs.clients + i;
2380 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2381 host_client = temp_client;
2384 //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)
2385 static void VM_SV_setattachment (void)
2387 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2388 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2389 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2393 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2395 if (e == prog->edicts)
2397 VM_Warning("setattachment: can not modify world entity\n");
2400 if (e->priv.server->free)
2402 VM_Warning("setattachment: can not modify free entity\n");
2406 if (tagentity == NULL)
2407 tagentity = prog->edicts;
2409 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2411 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2413 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2416 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2418 modelindex = (int)tagentity->fields.server->modelindex;
2419 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2421 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2423 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);
2426 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));
2430 /////////////////////////////////////////
2431 // DP_MD3_TAGINFO extension coded by VorteX
2433 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2438 i = (int)e->fields.server->modelindex;
2439 if (i < 1 || i >= MAX_MODELS)
2441 model = sv.models[i];
2443 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2446 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2448 float scale = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale)->_float;
2452 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);
2454 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);
2457 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2463 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2464 && (model = sv.models[(int)ent->fields.server->modelindex])
2465 && model->animscenes)
2467 // if model has wrong frame, engine automatically switches to model first frame
2468 frame = (int)ent->fields.server->frame;
2469 if (frame < 0 || frame >= model->numframes)
2471 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2473 *out = identitymatrix;
2477 // Warnings/errors code:
2478 // 0 - normal (everything all-right)
2481 // 3 - null or non-precached model
2482 // 4 - no tags with requested index
2483 // 5 - runaway loop at attachment chain
2484 extern cvar_t cl_bob;
2485 extern cvar_t cl_bobcycle;
2486 extern cvar_t cl_bobup;
2487 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2491 int modelindex, attachloop;
2492 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2495 *out = identitymatrix; // warnings and errors return identical matrix
2497 if (ent == prog->edicts)
2499 if (ent->priv.server->free)
2502 modelindex = (int)ent->fields.server->modelindex;
2503 if (modelindex <= 0 || modelindex > MAX_MODELS)
2506 model = sv.models[modelindex];
2508 tagmatrix = identitymatrix;
2509 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2513 if (attachloop >= 256) // prevent runaway looping
2515 // apply transformation by child's tagindex on parent entity and then
2516 // by parent entity itself
2517 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2518 if (ret && attachloop == 0)
2520 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2521 SV_GetEntityMatrix(ent, &entitymatrix, false);
2522 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2523 // next iteration we process the parent entity
2524 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2526 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2527 ent = PRVM_EDICT_NUM(val->edict);
2534 // RENDER_VIEWMODEL magic
2535 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2537 Matrix4x4_Copy(&tagmatrix, out);
2538 ent = PRVM_EDICT_NUM(val->edict);
2540 SV_GetEntityMatrix(ent, &entitymatrix, true);
2541 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2544 // Cl_bob, ported from rendering code
2545 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2548 // LordHavoc: this code is *weird*, but not replacable (I think it
2549 // should be done in QC on the server, but oh well, quake is quake)
2550 // LordHavoc: figured out bobup: the time at which the sin is at 180
2551 // degrees (which allows lengthening or squishing the peak or valley)
2552 cycle = sv.time/cl_bobcycle.value;
2553 cycle -= (int)cycle;
2554 if (cycle < cl_bobup.value)
2555 cycle = sin(M_PI * cycle / cl_bobup.value);
2557 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2558 // bob is proportional to velocity in the xy plane
2559 // (don't count Z, or jumping messes it up)
2560 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;
2561 bob = bob*0.3 + bob*0.7*cycle;
2562 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2569 //float(entity ent, string tagname) gettagindex;
2571 static void VM_SV_gettagindex (void)
2574 const char *tag_name;
2575 int modelindex, tag_index;
2577 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2579 ent = PRVM_G_EDICT(OFS_PARM0);
2580 tag_name = PRVM_G_STRING(OFS_PARM1);
2582 if (ent == prog->edicts)
2584 VM_Warning("gettagindex: can't affect world entity\n");
2587 if (ent->priv.server->free)
2589 VM_Warning("gettagindex: can't affect free entity\n");
2593 modelindex = (int)ent->fields.server->modelindex;
2595 if (modelindex <= 0 || modelindex > MAX_MODELS)
2596 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2599 tag_index = SV_GetTagIndex(ent, tag_name);
2601 if(developer.integer >= 100)
2602 Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2604 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2607 //vector(entity ent, float tagindex) gettaginfo;
2608 static void VM_SV_gettaginfo (void)
2612 matrix4x4_t tag_matrix;
2615 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2617 e = PRVM_G_EDICT(OFS_PARM0);
2618 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2620 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2621 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2626 VM_Warning("gettagindex: can't affect world entity\n");
2629 VM_Warning("gettagindex: can't affect free entity\n");
2632 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2635 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2638 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2643 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2644 static void VM_SV_dropclient (void)
2647 client_t *oldhostclient;
2648 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2649 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2650 if (clientnum < 0 || clientnum >= svs.maxclients)
2652 VM_Warning("dropclient: not a client\n");
2655 if (!svs.clients[clientnum].active)
2657 VM_Warning("dropclient: that client slot is not connected\n");
2660 oldhostclient = host_client;
2661 host_client = svs.clients + clientnum;
2662 SV_DropClient(false);
2663 host_client = oldhostclient;
2666 //entity() spawnclient (DP_SV_BOTCLIENT)
2667 static void VM_SV_spawnclient (void)
2671 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2672 prog->xfunction->builtinsprofile += 2;
2674 for (i = 0;i < svs.maxclients;i++)
2676 if (!svs.clients[i].active)
2678 prog->xfunction->builtinsprofile += 100;
2679 SV_ConnectClient (i, NULL);
2680 // this has to be set or else ClientDisconnect won't be called
2681 // we assume the qc will call ClientConnect...
2682 svs.clients[i].clientconnectcalled = true;
2683 ed = PRVM_EDICT_NUM(i + 1);
2687 VM_RETURN_EDICT(ed);
2690 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2691 static void VM_SV_clienttype (void)
2694 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2695 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2696 if (clientnum < 0 || clientnum >= svs.maxclients)
2697 PRVM_G_FLOAT(OFS_RETURN) = 3;
2698 else if (!svs.clients[clientnum].active)
2699 PRVM_G_FLOAT(OFS_RETURN) = 0;
2700 else if (svs.clients[clientnum].netconnection)
2701 PRVM_G_FLOAT(OFS_RETURN) = 1;
2703 PRVM_G_FLOAT(OFS_RETURN) = 2;
2710 string(string key) serverkey
2713 void VM_SV_serverkey(void)
2715 char string[VM_STRINGTEMP_LENGTH];
2716 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2717 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2718 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2721 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2722 static void VM_SV_setmodelindex (void)
2727 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2729 e = PRVM_G_EDICT(OFS_PARM0);
2730 if (e == prog->edicts)
2732 VM_Warning("setmodelindex: can not modify world entity\n");
2735 if (e->priv.server->free)
2737 VM_Warning("setmodelindex: can not modify free entity\n");
2740 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2741 if (i <= 0 || i > MAX_MODELS)
2743 VM_Warning("setmodelindex: invalid modelindex\n");
2746 if (!sv.model_precache[i][0])
2748 VM_Warning("setmodelindex: model not precached\n");
2752 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2753 e->fields.server->modelindex = i;
2759 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2760 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2762 SetMinMaxSize (e, quakemins, quakemaxs, true);
2765 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2768 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2769 static void VM_SV_modelnameforindex (void)
2772 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2774 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2776 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2777 if (i <= 0 || i > MAX_MODELS)
2779 VM_Warning("modelnameforindex: invalid modelindex\n");
2782 if (!sv.model_precache[i][0])
2784 VM_Warning("modelnameforindex: model not precached\n");
2788 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2791 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2792 static void VM_SV_particleeffectnum (void)
2795 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2796 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2799 PRVM_G_FLOAT(OFS_RETURN) = i;
2802 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2803 static void VM_SV_trailparticles (void)
2805 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2807 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2808 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2809 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2810 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2811 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2812 SV_FlushBroadcastMessages();
2815 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2816 static void VM_SV_pointparticles (void)
2818 int effectnum, count;
2820 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2821 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2822 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2823 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2824 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2825 if (count == 1 && !VectorLength2(vel))
2828 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2829 MSG_WriteShort(&sv.datagram, effectnum);
2830 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2834 // 1+2+12+12+2=29 bytes
2835 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2836 MSG_WriteShort(&sv.datagram, effectnum);
2837 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2838 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2839 MSG_WriteShort(&sv.datagram, count);
2842 SV_FlushBroadcastMessages();
2845 prvm_builtin_t vm_sv_builtins[] = {
2846 NULL, // #0 NULL function (not callable) (QUAKE)
2847 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
2848 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
2849 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
2850 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
2851 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
2852 VM_break, // #6 void() break (QUAKE)
2853 VM_random, // #7 float() random (QUAKE)
2854 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
2855 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
2856 VM_error, // #10 void(string e) error (QUAKE)
2857 VM_objerror, // #11 void(string e) objerror (QUAKE)
2858 VM_vlen, // #12 float(vector v) vlen (QUAKE)
2859 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
2860 VM_spawn, // #14 entity() spawn (QUAKE)
2861 VM_remove, // #15 void(entity e) remove (QUAKE)
2862 VM_SV_traceline, // #16 float(vector v1, vector v2, float tryents) traceline (QUAKE)
2863 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
2864 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
2865 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
2866 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
2867 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
2868 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
2869 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
2870 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
2871 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
2872 VM_ftos, // #26 string(float f) ftos (QUAKE)
2873 VM_vtos, // #27 string(vector v) vtos (QUAKE)
2874 VM_coredump, // #28 void() coredump (QUAKE)
2875 VM_traceon, // #29 void() traceon (QUAKE)
2876 VM_traceoff, // #30 void() traceoff (QUAKE)
2877 VM_eprint, // #31 void(entity e) eprint (QUAKE)
2878 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
2879 NULL, // #33 (QUAKE)
2880 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
2881 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
2882 VM_rint, // #36 float(float v) rint (QUAKE)
2883 VM_floor, // #37 float(float v) floor (QUAKE)
2884 VM_ceil, // #38 float(float v) ceil (QUAKE)
2885 NULL, // #39 (QUAKE)
2886 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
2887 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
2888 NULL, // #42 (QUAKE)
2889 VM_fabs, // #43 float(float f) fabs (QUAKE)
2890 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
2891 VM_cvar, // #45 float(string s) cvar (QUAKE)
2892 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
2893 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
2894 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
2895 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
2896 NULL, // #50 (QUAKE)
2897 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
2898 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
2899 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
2900 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
2901 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
2902 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
2903 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
2904 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
2905 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
2906 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
2907 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
2908 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
2909 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
2910 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
2911 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
2912 NULL, // #66 (QUAKE)
2913 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
2914 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
2915 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
2916 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
2917 NULL, // #71 (QUAKE)
2918 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
2919 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
2920 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
2921 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
2922 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
2923 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
2924 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
2925 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
2926 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
2927 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2928 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
2929 NULL, // #83 (QUAKE)
2930 NULL, // #84 (QUAKE)
2931 NULL, // #85 (QUAKE)
2932 NULL, // #86 (QUAKE)
2933 NULL, // #87 (QUAKE)
2934 NULL, // #88 (QUAKE)
2935 NULL, // #89 (QUAKE)
2936 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2937 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2938 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2939 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2940 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2941 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2942 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2943 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2944 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2945 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2946 // FrikaC and Telejano range #100-#199
2957 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2958 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2959 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2960 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2961 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2962 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
2963 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2964 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2965 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2966 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3047 // FTEQW range #200-#299
3066 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3069 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3070 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3071 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3072 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3073 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3074 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3075 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3076 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3077 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3078 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3080 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3148 // CSQC range #300-#399
3149 NULL, // #300 void() clearscene (EXT_CSQC)
3150 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3151 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3152 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3153 NULL, // #304 void() renderscene (EXT_CSQC)
3154 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3155 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3156 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3157 NULL, // #308 void() R_EndPolygon
3159 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3160 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3164 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3165 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3166 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3167 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3168 NULL, // #319 void(string name) freepic (EXT_CSQC)
3169 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3170 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3171 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3172 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3173 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3174 NULL, // #325 void(void) drawresetcliparea
3179 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3180 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3181 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3182 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3183 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3184 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3185 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3186 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3187 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3188 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3189 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3190 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3191 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3192 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3193 NULL, // #344 vector() getmousepos (EXT_CSQC)
3194 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3195 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3196 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3197 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3198 NULL, // #349 float() isdemo (EXT_CSQC)
3199 VM_isserver, // #350 float() isserver (EXT_CSQC)
3200 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3201 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3202 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3203 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3209 NULL, // #360 float() readbyte (EXT_CSQC)
3210 NULL, // #361 float() readchar (EXT_CSQC)
3211 NULL, // #362 float() readshort (EXT_CSQC)
3212 NULL, // #363 float() readlong (EXT_CSQC)
3213 NULL, // #364 float() readcoord (EXT_CSQC)
3214 NULL, // #365 float() readangle (EXT_CSQC)
3215 NULL, // #366 string() readstring (EXT_CSQC)
3216 NULL, // #367 float() readfloat (EXT_CSQC)
3249 // LordHavoc's range #400-#499
3250 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3251 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3252 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3253 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3254 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3255 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3256 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3257 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3258 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)
3259 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3260 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3261 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3262 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3263 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3264 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3265 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3266 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3267 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3268 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3269 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3270 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3271 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3272 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3273 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3274 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3275 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3276 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3277 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3278 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3279 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3280 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3281 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3282 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3283 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3284 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3285 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3286 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3287 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3288 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3289 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3290 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3291 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3292 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3293 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3294 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3295 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3296 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3297 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3298 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3299 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3300 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3301 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3302 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3303 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3304 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3305 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3306 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3307 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3309 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3310 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3311 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3312 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3313 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3314 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3315 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3316 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3317 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3318 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3319 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3321 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3322 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3323 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3324 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3325 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3326 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3327 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3328 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3329 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3330 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3331 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3332 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3333 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3334 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3335 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3336 VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3344 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3352 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3354 void VM_SV_Cmd_Init(void)
3359 void VM_SV_Cmd_Reset(void)
3361 if(prog->funcoffsets.SV_Shutdown)
3363 func_t s = prog->funcoffsets.SV_Shutdown;
3364 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3365 PRVM_ExecuteProgram(s,"SV_Shutdown() required");