6 //============================================================================
11 char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
35 "DP_ENT_CUSTOMCOLORMAP "
36 "DP_ENT_EXTERIORMODELTOCLIENT "
38 "DP_ENT_LOWPRECISION "
42 "DP_GFX_EXTERNALTEXTURES "
43 "DP_GFX_EXTERNALTEXTURES_PERMAP "
45 "DP_GFX_QUAKE3MODELTAGS "
49 "DP_HALFLIFE_MAP_CVAR "
55 "DP_MOVETYPEBOUNCEMISSILE "
57 "DP_QC_ASINACOSATANATAN2TAN "
62 "DP_QC_CVAR_DEFSTRING "
69 "DP_QC_FINDCHAINFLAGS "
70 "DP_QC_FINDCHAINFLOAT "
76 "DP_QC_GETSURFACEPOINTATTRIBUTE "
79 "DP_QC_MULTIPLETEMPSTRINGS "
80 "DP_QC_NUM_FOR_EDICT "
82 "DP_QC_SINCOSSQRTPOW "
84 "DP_QC_STRINGBUFFERS "
85 "DP_QC_STRINGCOLORFUNCTIONS "
86 "DP_QC_STRING_CASE_FUNCTIONS "
88 "DP_QC_TOKENIZEBYSEPARATOR "
91 "DP_QC_TRACE_MOVETYPE_HITMODEL "
92 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
93 "DP_QC_UNLIMITEDTEMPSTRINGS "
95 "DP_QC_VECTOANGLES_WITH_ROLL "
96 "DP_QC_VECTORVECTORS "
103 "DP_SND_DIRECTIONLESSATTNNONE "
110 "DP_SV_CLIENTCOLORS "
113 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
114 "DP_SV_DRAWONLYTOCLIENT "
117 "DP_SV_ENTITYCONTENTSTRANSITION "
118 "DP_SV_MODELFLAGS_AS_EFFECTS "
119 "DP_SV_MOVETYPESTEP_LANDEVENT "
121 "DP_SV_NODRAWTOCLIENT "
122 "DP_SV_ONENTITYNOSPAWNFUNCTION "
124 "DP_SV_PLAYERPHYSICS "
125 "DP_SV_POINTPARTICLES "
127 "DP_SV_PRECACHEANYTIME "
131 "DP_SV_ROTATINGBMODEL "
135 "DP_SV_SPAWNFUNC_PREFIX "
136 "DP_SV_WRITEPICTURE "
137 "DP_SV_WRITEUNTERMINATEDSTRING "
141 "DP_TE_EXPLOSIONRGB "
143 "DP_TE_PARTICLECUBE "
144 "DP_TE_PARTICLERAIN "
145 "DP_TE_PARTICLESNOW "
147 "DP_TE_QUADEFFECTS1 "
150 "DP_TE_STANDARDEFFECTBUILTINS "
151 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
156 "KRIMZON_SV_PARSECLIENTCOMMAND "
159 "NEXUIZ_PLAYERMODEL "
161 "PRYDON_CLIENTCURSOR "
162 "TENEBRAE_GFX_DLIGHTS "
164 //"EXT_CSQC " // not ready yet
171 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.
173 setorigin (entity, origin)
176 static void VM_SV_setorigin (void)
181 VM_SAFEPARMCOUNT(2, VM_setorigin);
183 e = PRVM_G_EDICT(OFS_PARM0);
184 if (e == prog->edicts)
186 VM_Warning("setorigin: can not modify world entity\n");
189 if (e->priv.server->free)
191 VM_Warning("setorigin: can not modify free entity\n");
194 org = PRVM_G_VECTOR(OFS_PARM1);
195 VectorCopy (org, e->fields.server->origin);
196 SV_LinkEdict (e, false);
199 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
200 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
204 for (i=0 ; i<3 ; i++)
206 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
208 // set derived values
209 VectorCopy (min, e->fields.server->mins);
210 VectorCopy (max, e->fields.server->maxs);
211 VectorSubtract (max, min, e->fields.server->size);
213 SV_LinkEdict (e, false);
220 the size box is rotated by the current angle
221 LordHavoc: no it isn't...
223 setsize (entity, minvector, maxvector)
226 static void VM_SV_setsize (void)
231 VM_SAFEPARMCOUNT(3, VM_setsize);
233 e = PRVM_G_EDICT(OFS_PARM0);
234 if (e == prog->edicts)
236 VM_Warning("setsize: can not modify world entity\n");
239 if (e->priv.server->free)
241 VM_Warning("setsize: can not modify free entity\n");
244 min = PRVM_G_VECTOR(OFS_PARM1);
245 max = PRVM_G_VECTOR(OFS_PARM2);
246 SetMinMaxSize (e, min, max, false);
254 setmodel(entity, model)
257 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
258 static void VM_SV_setmodel (void)
264 VM_SAFEPARMCOUNT(2, VM_setmodel);
266 e = PRVM_G_EDICT(OFS_PARM0);
267 if (e == prog->edicts)
269 VM_Warning("setmodel: can not modify world entity\n");
272 if (e->priv.server->free)
274 VM_Warning("setmodel: can not modify free entity\n");
277 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
278 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
279 e->fields.server->modelindex = i;
285 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
286 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
288 SetMinMaxSize (e, quakemins, quakemaxs, true);
291 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
298 single print to a specific client
300 sprint(clientent, value)
303 static void VM_SV_sprint (void)
307 char string[VM_STRINGTEMP_LENGTH];
309 VM_VarString(1, string, sizeof(string));
311 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
313 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
314 // LordHavoc: div0 requested that sprintto world operate like print
321 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
323 VM_Warning("tried to centerprint to a non-client\n");
327 client = svs.clients + entnum-1;
328 if (!client->netconnection)
331 MSG_WriteChar(&client->netconnection->message,svc_print);
332 MSG_WriteString(&client->netconnection->message, string);
340 single print to a specific client
342 centerprint(clientent, value)
345 static void VM_SV_centerprint (void)
349 char string[VM_STRINGTEMP_LENGTH];
351 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
353 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
355 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
357 VM_Warning("tried to centerprint to a non-client\n");
361 client = svs.clients + entnum-1;
362 if (!client->netconnection)
365 VM_VarString(1, string, sizeof(string));
366 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
367 MSG_WriteString(&client->netconnection->message, string);
374 particle(origin, color, count)
377 static void VM_SV_particle (void)
383 VM_SAFEPARMCOUNT(4, VM_SV_particle);
385 org = PRVM_G_VECTOR(OFS_PARM0);
386 dir = PRVM_G_VECTOR(OFS_PARM1);
387 color = PRVM_G_FLOAT(OFS_PARM2);
388 count = PRVM_G_FLOAT(OFS_PARM3);
389 SV_StartParticle (org, dir, (int)color, (int)count);
399 static void VM_SV_ambientsound (void)
403 float vol, attenuation;
406 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
408 pos = PRVM_G_VECTOR (OFS_PARM0);
409 samp = PRVM_G_STRING(OFS_PARM1);
410 vol = PRVM_G_FLOAT(OFS_PARM2);
411 attenuation = PRVM_G_FLOAT(OFS_PARM3);
413 // check to see if samp was properly precached
414 soundnum = SV_SoundIndex(samp, 1);
422 // add an svc_spawnambient command to the level signon packet
425 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
427 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
429 MSG_WriteVector(&sv.signon, pos, sv.protocol);
431 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
432 MSG_WriteShort (&sv.signon, soundnum);
434 MSG_WriteByte (&sv.signon, soundnum);
436 MSG_WriteByte (&sv.signon, (int)(vol*255));
437 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
445 Each entity can have eight independant sound sources, like voice,
448 Channel 0 is an auto-allocate channel, the others override anything
449 already running on that entity/channel pair.
451 An attenuation of 0 will play full volume everywhere in the level.
452 Larger attenuations will drop off.
456 static void VM_SV_sound (void)
460 prvm_edict_t *entity;
464 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
466 entity = PRVM_G_EDICT(OFS_PARM0);
467 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
468 sample = PRVM_G_STRING(OFS_PARM2);
469 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
470 attenuation = PRVM_G_FLOAT(OFS_PARM4);
473 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
477 if (volume < 0 || volume > 255)
479 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
483 if (attenuation < 0 || attenuation > 4)
485 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
489 if (channel < 0 || channel > 7)
491 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
495 SV_StartSound (entity, channel, sample, volume, attenuation);
502 Follows the same logic as VM_SV_sound, except instead of
503 an entity, an origin for the sound is provided, and channel
504 is omitted (since no entity is being tracked).
508 static void VM_SV_pointsound(void)
515 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
517 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
518 sample = PRVM_G_STRING(OFS_PARM1);
519 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
520 attenuation = PRVM_G_FLOAT(OFS_PARM3);
522 if (volume < 0 || volume > 255)
524 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
528 if (attenuation < 0 || attenuation > 4)
530 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
534 SV_StartPointSound (org, sample, volume, attenuation);
541 Used for use tracing and shot targeting
542 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
543 if the tryents flag is set.
545 traceline (vector1, vector2, movetype, ignore)
548 static void VM_SV_traceline (void)
555 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
557 prog->xfunction->builtinsprofile += 30;
559 v1 = PRVM_G_VECTOR(OFS_PARM0);
560 v2 = PRVM_G_VECTOR(OFS_PARM1);
561 move = (int)PRVM_G_FLOAT(OFS_PARM2);
562 ent = PRVM_G_EDICT(OFS_PARM3);
564 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]))
565 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));
567 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
569 VM_SetTraceGlobals(&trace);
577 Used for use tracing and shot targeting
578 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
579 if the tryents flag is set.
581 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
584 // LordHavoc: added this for my own use, VERY useful, similar to traceline
585 static void VM_SV_tracebox (void)
587 float *v1, *v2, *m1, *m2;
592 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
594 prog->xfunction->builtinsprofile += 30;
596 v1 = PRVM_G_VECTOR(OFS_PARM0);
597 m1 = PRVM_G_VECTOR(OFS_PARM1);
598 m2 = PRVM_G_VECTOR(OFS_PARM2);
599 v2 = PRVM_G_VECTOR(OFS_PARM3);
600 move = (int)PRVM_G_FLOAT(OFS_PARM4);
601 ent = PRVM_G_EDICT(OFS_PARM5);
603 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]))
604 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));
606 trace = SV_Move (v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
608 VM_SetTraceGlobals(&trace);
611 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
616 vec3_t original_origin;
617 vec3_t original_velocity;
618 vec3_t original_angles;
619 vec3_t original_avelocity;
623 VectorCopy(tossent->fields.server->origin , original_origin );
624 VectorCopy(tossent->fields.server->velocity , original_velocity );
625 VectorCopy(tossent->fields.server->angles , original_angles );
626 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
628 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
629 if (val != NULL && val->_float != 0)
630 gravity = val->_float;
633 gravity *= sv_gravity.value * 0.05;
635 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
637 SV_CheckVelocity (tossent);
638 tossent->fields.server->velocity[2] -= gravity;
639 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
640 VectorScale (tossent->fields.server->velocity, 0.05, move);
641 VectorAdd (tossent->fields.server->origin, move, end);
642 trace = SV_Move (tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
643 VectorCopy (trace.endpos, tossent->fields.server->origin);
645 if (trace.fraction < 1)
649 VectorCopy(original_origin , tossent->fields.server->origin );
650 VectorCopy(original_velocity , tossent->fields.server->velocity );
651 VectorCopy(original_angles , tossent->fields.server->angles );
652 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
657 static void VM_SV_tracetoss (void)
661 prvm_edict_t *ignore;
663 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
665 prog->xfunction->builtinsprofile += 600;
667 ent = PRVM_G_EDICT(OFS_PARM0);
668 if (ent == prog->edicts)
670 VM_Warning("tracetoss: can not use world entity\n");
673 ignore = PRVM_G_EDICT(OFS_PARM1);
675 trace = SV_Trace_Toss (ent, ignore);
677 VM_SetTraceGlobals(&trace);
680 //============================================================================
682 static int checkpvsbytes;
683 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
685 static int VM_SV_newcheckclient (int check)
691 // cycle to the next one
693 check = bound(1, check, svs.maxclients);
694 if (check == svs.maxclients)
702 prog->xfunction->builtinsprofile++;
704 if (i == svs.maxclients+1)
706 // look up the client's edict
707 ent = PRVM_EDICT_NUM(i);
708 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
709 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
711 // found a valid client (possibly the same one again)
715 // get the PVS for the entity
716 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
718 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
719 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
728 Returns a client (or object that has a client enemy) that would be a
731 If there is more than one valid option, they are cycled each frame
733 If (self.origin + self.viewofs) is not in the PVS of the current target,
734 it is not returned at all.
739 int c_invis, c_notvis;
740 static void VM_SV_checkclient (void)
742 prvm_edict_t *ent, *self;
745 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
747 // find a new check if on a new frame
748 if (sv.time - sv.lastchecktime >= 0.1)
750 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
751 sv.lastchecktime = sv.time;
754 // return check if it might be visible
755 ent = PRVM_EDICT_NUM(sv.lastcheck);
756 if (ent->priv.server->free || ent->fields.server->health <= 0)
758 VM_RETURN_EDICT(prog->edicts);
762 // if current entity can't possibly see the check entity, return 0
763 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
764 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
765 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
768 VM_RETURN_EDICT(prog->edicts);
772 // might be able to see it
774 VM_RETURN_EDICT(ent);
777 //============================================================================
784 Sends text over to the client's execution buffer
786 stuffcmd (clientent, value, ...)
789 static void VM_SV_stuffcmd (void)
793 char string[VM_STRINGTEMP_LENGTH];
795 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
797 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
798 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
800 VM_Warning("Can't stuffcmd to a non-client\n");
804 VM_VarString(1, string, sizeof(string));
807 host_client = svs.clients + entnum-1;
808 Host_ClientCommands ("%s", string);
816 Returns a chain of entities that have origins within a spherical area
818 findradius (origin, radius)
821 static void VM_SV_findradius (void)
823 prvm_edict_t *ent, *chain;
824 vec_t radius, radius2;
825 vec3_t org, eorg, mins, maxs;
828 prvm_edict_t *touchedicts[MAX_EDICTS];
830 VM_SAFEPARMCOUNT(2, VM_SV_findradius);
832 chain = (prvm_edict_t *)prog->edicts;
834 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
835 radius = PRVM_G_FLOAT(OFS_PARM1);
836 radius2 = radius * radius;
838 mins[0] = org[0] - (radius + 1);
839 mins[1] = org[1] - (radius + 1);
840 mins[2] = org[2] - (radius + 1);
841 maxs[0] = org[0] + (radius + 1);
842 maxs[1] = org[1] + (radius + 1);
843 maxs[2] = org[2] + (radius + 1);
844 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
845 if (numtouchedicts > MAX_EDICTS)
847 // this never happens
848 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
849 numtouchedicts = MAX_EDICTS;
851 for (i = 0;i < numtouchedicts;i++)
853 ent = touchedicts[i];
854 prog->xfunction->builtinsprofile++;
855 // Quake did not return non-solid entities but darkplaces does
856 // (note: this is the reason you can't blow up fallen zombies)
857 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
859 // LordHavoc: compare against bounding box rather than center so it
860 // doesn't miss large objects, and use DotProduct instead of Length
861 // for a major speedup
862 VectorSubtract(org, ent->fields.server->origin, eorg);
863 if (sv_gameplayfix_findradiusdistancetobox.integer)
865 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
866 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
867 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
870 VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
871 if (DotProduct(eorg, eorg) < radius2)
873 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
878 VM_RETURN_EDICT(chain);
881 static void VM_SV_precache_sound (void)
883 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
884 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
887 static void VM_SV_precache_model (void)
889 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
890 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
891 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
898 float(float yaw, float dist[, settrace]) walkmove
901 static void VM_SV_walkmove (void)
910 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
912 // assume failure if it returns early
913 PRVM_G_FLOAT(OFS_RETURN) = 0;
915 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
916 if (ent == prog->edicts)
918 VM_Warning("walkmove: can not modify world entity\n");
921 if (ent->priv.server->free)
923 VM_Warning("walkmove: can not modify free entity\n");
926 yaw = PRVM_G_FLOAT(OFS_PARM0);
927 dist = PRVM_G_FLOAT(OFS_PARM1);
928 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
930 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
933 yaw = yaw*M_PI*2 / 360;
935 move[0] = cos(yaw)*dist;
936 move[1] = sin(yaw)*dist;
939 // save program state, because SV_movestep may call other progs
940 oldf = prog->xfunction;
941 oldself = prog->globals.server->self;
943 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
946 // restore program state
947 prog->xfunction = oldf;
948 prog->globals.server->self = oldself;
958 static void VM_SV_droptofloor (void)
964 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
966 // assume failure if it returns early
967 PRVM_G_FLOAT(OFS_RETURN) = 0;
969 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
970 if (ent == prog->edicts)
972 VM_Warning("droptofloor: can not modify world entity\n");
975 if (ent->priv.server->free)
977 VM_Warning("droptofloor: can not modify free entity\n");
981 VectorCopy (ent->fields.server->origin, end);
984 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
985 SV_UnstickEntity(ent);
987 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
988 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
991 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]);
992 VectorAdd(ent->fields.server->origin, offset, org);
993 trace = SV_Move (org, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
994 VectorSubtract(trace.endpos, offset, trace.endpos);
995 if (trace.startsolid)
997 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]);
998 SV_UnstickEntity(ent);
999 SV_LinkEdict (ent, false);
1000 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1001 ent->fields.server->groundentity = 0;
1002 PRVM_G_FLOAT(OFS_RETURN) = 1;
1004 else if (trace.fraction < 1)
1006 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]);
1007 VectorCopy (trace.endpos, ent->fields.server->origin);
1008 SV_UnstickEntity(ent);
1009 SV_LinkEdict (ent, false);
1010 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1011 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1012 PRVM_G_FLOAT(OFS_RETURN) = 1;
1013 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1014 ent->priv.server->suspendedinairflag = true;
1019 if (trace.fraction != 1)
1021 if (trace.fraction < 1)
1022 VectorCopy (trace.endpos, ent->fields.server->origin);
1023 SV_LinkEdict (ent, false);
1024 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1025 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1026 PRVM_G_FLOAT(OFS_RETURN) = 1;
1027 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1028 ent->priv.server->suspendedinairflag = true;
1037 void(float style, string value) lightstyle
1040 static void VM_SV_lightstyle (void)
1047 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1049 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1050 val = PRVM_G_STRING(OFS_PARM1);
1052 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1053 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1056 // change the string in sv
1057 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1059 // send message to all clients on this server
1060 if (sv.state != ss_active)
1063 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1065 if (client->active && client->netconnection)
1067 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1068 MSG_WriteChar (&client->netconnection->message,style);
1069 MSG_WriteString (&client->netconnection->message, val);
1079 static void VM_SV_checkbottom (void)
1081 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1082 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1090 static void VM_SV_pointcontents (void)
1092 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1093 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1100 Pick a vector for the player to shoot along
1101 vector aim(entity, missilespeed)
1104 static void VM_SV_aim (void)
1106 prvm_edict_t *ent, *check, *bestent;
1107 vec3_t start, dir, end, bestdir;
1110 float dist, bestdist;
1113 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1115 // assume failure if it returns early
1116 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1117 // if sv_aim is so high it can't possibly accept anything, skip out early
1118 if (sv_aim.value >= 1)
1121 ent = PRVM_G_EDICT(OFS_PARM0);
1122 if (ent == prog->edicts)
1124 VM_Warning("aim: can not use world entity\n");
1127 if (ent->priv.server->free)
1129 VM_Warning("aim: can not use free entity\n");
1132 speed = PRVM_G_FLOAT(OFS_PARM1);
1134 VectorCopy (ent->fields.server->origin, start);
1137 // try sending a trace straight
1138 VectorCopy (prog->globals.server->v_forward, dir);
1139 VectorMA (start, 2048, dir, end);
1140 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1141 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1142 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1144 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1149 // try all possible entities
1150 VectorCopy (dir, bestdir);
1151 bestdist = sv_aim.value;
1154 check = PRVM_NEXT_EDICT(prog->edicts);
1155 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1157 prog->xfunction->builtinsprofile++;
1158 if (check->fields.server->takedamage != DAMAGE_AIM)
1162 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1163 continue; // don't aim at teammate
1164 for (j=0 ; j<3 ; j++)
1165 end[j] = check->fields.server->origin[j]
1166 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1167 VectorSubtract (end, start, dir);
1168 VectorNormalize (dir);
1169 dist = DotProduct (dir, prog->globals.server->v_forward);
1170 if (dist < bestdist)
1171 continue; // to far to turn
1172 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1173 if (tr.ent == check)
1174 { // can shoot at this one
1182 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1183 dist = DotProduct (dir, prog->globals.server->v_forward);
1184 VectorScale (prog->globals.server->v_forward, dist, end);
1186 VectorNormalize (end);
1187 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1191 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1196 ===============================================================================
1200 ===============================================================================
1203 #define MSG_BROADCAST 0 // unreliable to all
1204 #define MSG_ONE 1 // reliable to one (msg_entity)
1205 #define MSG_ALL 2 // reliable to all
1206 #define MSG_INIT 3 // write to the init string
1207 #define MSG_ENTITY 5
1209 sizebuf_t *WriteDest (void)
1215 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1219 return &sv.datagram;
1222 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1223 entnum = PRVM_NUM_FOR_EDICT(ent);
1224 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1226 VM_Warning ("WriteDest: tried to write to non-client\n");
1227 return &sv.reliable_datagram;
1230 return &svs.clients[entnum-1].netconnection->message;
1233 VM_Warning ("WriteDest: bad destination\n");
1235 return &sv.reliable_datagram;
1241 return sv.writeentitiestoclient_msg;
1247 static void VM_SV_WriteByte (void)
1249 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1250 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1253 static void VM_SV_WriteChar (void)
1255 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1256 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1259 static void VM_SV_WriteShort (void)
1261 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1262 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1265 static void VM_SV_WriteLong (void)
1267 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1268 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1271 static void VM_SV_WriteAngle (void)
1273 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1274 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1277 static void VM_SV_WriteCoord (void)
1279 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1280 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1283 static void VM_SV_WriteString (void)
1285 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1286 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1289 static void VM_SV_WriteUnterminatedString (void)
1291 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1292 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1296 static void VM_SV_WriteEntity (void)
1298 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1299 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1302 // writes a picture as at most size bytes of data
1304 // IMGNAME \0 SIZE(short) IMGDATA
1305 // if failed to read/compress:
1307 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1308 static void VM_SV_WritePicture (void)
1310 const char *imgname;
1314 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1316 imgname = PRVM_G_STRING(OFS_PARM1);
1317 size = PRVM_G_FLOAT(OFS_PARM2);
1321 MSG_WriteString(WriteDest(), imgname);
1322 if(Image_Compress(imgname, size, &buf, &size))
1325 MSG_WriteShort(WriteDest(), size);
1326 SZ_Write(WriteDest(), buf, size);
1331 MSG_WriteShort(WriteDest(), 0);
1335 //////////////////////////////////////////////////////////
1337 static void VM_SV_makestatic (void)
1342 // allow 0 parameters due to an id1 qc bug in which this function is used
1343 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1344 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1346 if (prog->argc >= 1)
1347 ent = PRVM_G_EDICT(OFS_PARM0);
1349 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1350 if (ent == prog->edicts)
1352 VM_Warning("makestatic: can not modify world entity\n");
1355 if (ent->priv.server->free)
1357 VM_Warning("makestatic: can not modify free entity\n");
1362 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1367 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1368 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1369 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1371 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1373 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1374 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1375 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1379 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1380 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1381 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1384 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1385 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1386 for (i=0 ; i<3 ; i++)
1388 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1389 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1392 // throw the entity away now
1396 //=============================================================================
1403 static void VM_SV_setspawnparms (void)
1409 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1411 ent = PRVM_G_EDICT(OFS_PARM0);
1412 i = PRVM_NUM_FOR_EDICT(ent);
1413 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1415 Con_Print("tried to setspawnparms on a non-client\n");
1419 // copy spawn parms out of the client_t
1420 client = svs.clients + i-1;
1421 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1422 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1429 Returns a color vector indicating the lighting at the requested point.
1431 (Internal Operation note: actually measures the light beneath the point, just like
1432 the model lighting on the client)
1437 static void VM_SV_getlight (void)
1439 vec3_t ambientcolor, diffusecolor, diffusenormal;
1441 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1442 p = PRVM_G_VECTOR(OFS_PARM0);
1443 VectorClear(ambientcolor);
1444 VectorClear(diffusecolor);
1445 VectorClear(diffusenormal);
1446 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1447 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1448 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1453 unsigned char type; // 1/2/8 or other value if isn't used
1457 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1458 static int vm_customstats_last;
1460 void VM_CustomStats_Clear (void)
1464 Z_Free(vm_customstats);
1465 vm_customstats = NULL;
1466 vm_customstats_last = -1;
1470 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1478 for(i=0; i<vm_customstats_last+1 ;i++)
1480 if(!vm_customstats[i].type)
1482 switch(vm_customstats[i].type)
1484 //string as 16 bytes
1487 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1488 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1489 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1490 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1491 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1493 //float field sent as-is
1495 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1497 //integer value of float field
1499 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1507 // void(float index, float type, .void field) SV_AddStat = #232;
1508 // Set up an auto-sent player stat.
1509 // Client's get thier own fields sent to them. Index may not be less than 32.
1510 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1511 // 1: string (4 stats carrying a total of 16 charactures)
1512 // 2: float (one stat, float converted to an integer for transportation)
1513 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1514 static void VM_SV_AddStat (void)
1519 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1523 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1526 VM_Warning("PF_SV_AddStat: not enough memory\n");
1530 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1531 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1532 off = PRVM_G_INT (OFS_PARM2);
1537 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1540 if(i >= (MAX_CL_STATS-32))
1542 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1545 if(i > (MAX_CL_STATS-32-4) && type == 1)
1547 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1550 vm_customstats[i].type = type;
1551 vm_customstats[i].fieldoffset = off;
1552 if(vm_customstats_last < i)
1553 vm_customstats_last = i;
1560 copies data from one entity to another
1562 copyentity(src, dst)
1565 static void VM_SV_copyentity (void)
1567 prvm_edict_t *in, *out;
1568 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1569 in = PRVM_G_EDICT(OFS_PARM0);
1570 if (in == prog->edicts)
1572 VM_Warning("copyentity: can not read world entity\n");
1575 if (in->priv.server->free)
1577 VM_Warning("copyentity: can not read free entity\n");
1580 out = PRVM_G_EDICT(OFS_PARM1);
1581 if (out == prog->edicts)
1583 VM_Warning("copyentity: can not modify world entity\n");
1586 if (out->priv.server->free)
1588 VM_Warning("copyentity: can not modify free entity\n");
1591 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1592 SV_LinkEdict(out, false);
1600 sets the color of a client and broadcasts the update to all connected clients
1602 setcolor(clientent, value)
1605 static void VM_SV_setcolor (void)
1611 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1612 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1613 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1615 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1617 Con_Print("tried to setcolor a non-client\n");
1621 client = svs.clients + entnum-1;
1624 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1626 client->edict->fields.server->team = (i & 15) + 1;
1629 if (client->old_colors != client->colors)
1631 client->old_colors = client->colors;
1632 // send notification to all clients
1633 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1634 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1635 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1643 effect(origin, modelname, startframe, framecount, framerate)
1646 static void VM_SV_effect (void)
1650 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1651 s = PRVM_G_STRING(OFS_PARM1);
1654 VM_Warning("effect: no model specified\n");
1658 i = SV_ModelIndex(s, 1);
1661 VM_Warning("effect: model not precached\n");
1665 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1667 VM_Warning("effect: framecount < 1\n");
1671 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1673 VM_Warning("effect: framerate < 1\n");
1677 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));
1680 static void VM_SV_te_blood (void)
1682 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1683 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1685 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1686 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1688 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1689 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1690 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1692 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1693 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1694 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1696 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1697 SV_FlushBroadcastMessages();
1700 static void VM_SV_te_bloodshower (void)
1702 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1703 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1705 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1706 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1708 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1709 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1710 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1712 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1713 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1714 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1716 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1718 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1719 SV_FlushBroadcastMessages();
1722 static void VM_SV_te_explosionrgb (void)
1724 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1725 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1726 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1728 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1729 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1730 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1732 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1733 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1734 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1735 SV_FlushBroadcastMessages();
1738 static void VM_SV_te_particlecube (void)
1740 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1741 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1743 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1744 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1746 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1747 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1748 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1750 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1751 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1752 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1754 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1755 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1756 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1758 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1760 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1761 // gravity true/false
1762 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1764 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1765 SV_FlushBroadcastMessages();
1768 static void VM_SV_te_particlerain (void)
1770 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1771 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1773 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1774 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1776 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1777 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1778 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1780 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1781 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1782 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1784 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1785 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1786 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1788 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1790 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1791 SV_FlushBroadcastMessages();
1794 static void VM_SV_te_particlesnow (void)
1796 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1797 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1799 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1800 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
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);
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1808 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1810 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1812 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1814 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1816 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1817 SV_FlushBroadcastMessages();
1820 static void VM_SV_te_spark (void)
1822 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1823 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1825 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1826 MSG_WriteByte(&sv.datagram, TE_SPARK);
1828 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1830 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1832 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1833 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1834 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1836 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1837 SV_FlushBroadcastMessages();
1840 static void VM_SV_te_gunshotquad (void)
1842 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1843 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1844 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1847 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1848 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1849 SV_FlushBroadcastMessages();
1852 static void VM_SV_te_spikequad (void)
1854 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1855 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1856 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1858 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1859 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1860 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1861 SV_FlushBroadcastMessages();
1864 static void VM_SV_te_superspikequad (void)
1866 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1867 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1868 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1870 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1873 SV_FlushBroadcastMessages();
1876 static void VM_SV_te_explosionquad (void)
1878 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
1879 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1880 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1882 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1883 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1884 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1885 SV_FlushBroadcastMessages();
1888 static void VM_SV_te_smallflash (void)
1890 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
1891 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1892 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1894 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1895 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1896 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1897 SV_FlushBroadcastMessages();
1900 static void VM_SV_te_customflash (void)
1902 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
1903 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1905 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1906 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
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);
1912 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1914 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1916 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1917 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1918 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1919 SV_FlushBroadcastMessages();
1922 static void VM_SV_te_gunshot (void)
1924 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
1925 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1926 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1931 SV_FlushBroadcastMessages();
1934 static void VM_SV_te_spike (void)
1936 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
1937 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1938 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1941 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1942 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1943 SV_FlushBroadcastMessages();
1946 static void VM_SV_te_superspike (void)
1948 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
1949 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1950 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1952 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1953 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1954 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1955 SV_FlushBroadcastMessages();
1958 static void VM_SV_te_explosion (void)
1960 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
1961 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1962 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1964 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1965 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1967 SV_FlushBroadcastMessages();
1970 static void VM_SV_te_tarexplosion (void)
1972 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
1973 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1974 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1976 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1977 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1978 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1979 SV_FlushBroadcastMessages();
1982 static void VM_SV_te_wizspike (void)
1984 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
1985 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1986 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1989 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1990 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1991 SV_FlushBroadcastMessages();
1994 static void VM_SV_te_knightspike (void)
1996 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
1997 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1998 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2000 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2001 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2002 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2003 SV_FlushBroadcastMessages();
2006 static void VM_SV_te_lavasplash (void)
2008 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2009 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2010 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2012 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2014 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2015 SV_FlushBroadcastMessages();
2018 static void VM_SV_te_teleport (void)
2020 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2021 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2022 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2024 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2025 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2026 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2027 SV_FlushBroadcastMessages();
2030 static void VM_SV_te_explosion2 (void)
2032 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2033 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2034 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2036 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2037 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2038 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2040 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2041 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2042 SV_FlushBroadcastMessages();
2045 static void VM_SV_te_lightning1 (void)
2047 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2048 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2049 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2051 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2054 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2055 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2058 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2059 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2060 SV_FlushBroadcastMessages();
2063 static void VM_SV_te_lightning2 (void)
2065 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2066 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2067 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2069 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2071 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2072 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2075 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2076 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2077 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2078 SV_FlushBroadcastMessages();
2081 static void VM_SV_te_lightning3 (void)
2083 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2084 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2085 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2087 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2089 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2090 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2091 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2093 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2094 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2095 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2096 SV_FlushBroadcastMessages();
2099 static void VM_SV_te_beam (void)
2101 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2102 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2103 MSG_WriteByte(&sv.datagram, TE_BEAM);
2105 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2107 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2108 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2109 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2111 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2112 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2113 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2114 SV_FlushBroadcastMessages();
2117 static void VM_SV_te_plasmaburn (void)
2119 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2120 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2121 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2122 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2123 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2124 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2125 SV_FlushBroadcastMessages();
2128 static void VM_SV_te_flamejet (void)
2130 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2131 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2132 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2134 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2135 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2136 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2138 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2139 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2140 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2142 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2143 SV_FlushBroadcastMessages();
2146 void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2149 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2151 bestdist = 1000000000;
2153 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2155 // clip original point to each triangle of the surface and find the
2156 // triangle that is closest
2157 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2158 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2159 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2160 TriangleNormal(v[0], v[1], v[2], facenormal);
2161 VectorNormalize(facenormal);
2162 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2163 VectorMA(p, offsetdist, facenormal, temp);
2164 for (j = 0, k = 2;j < 3;k = j, j++)
2166 VectorSubtract(v[k], v[j], edgenormal);
2167 CrossProduct(edgenormal, facenormal, sidenormal);
2168 VectorNormalize(sidenormal);
2169 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2171 VectorMA(temp, offsetdist, sidenormal, temp);
2173 dist = VectorDistance2(temp, p);
2174 if (bestdist > dist)
2177 VectorCopy(temp, out);
2182 static dp_model_t *getmodel(prvm_edict_t *ed)
2185 if (!ed || ed->priv.server->free)
2187 modelindex = (int)ed->fields.server->modelindex;
2188 if (modelindex < 1 || modelindex >= MAX_MODELS)
2190 return sv.models[modelindex];
2193 static msurface_t *getsurface(dp_model_t *model, int surfacenum)
2195 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2197 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2201 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2202 static void VM_SV_getsurfacenumpoints(void)
2205 msurface_t *surface;
2206 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints);
2207 // return 0 if no such surface
2208 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2210 PRVM_G_FLOAT(OFS_RETURN) = 0;
2214 // note: this (incorrectly) assumes it is a simple polygon
2215 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2217 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2218 static void VM_SV_getsurfacepoint(void)
2222 msurface_t *surface;
2224 VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint);
2225 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2226 ed = PRVM_G_EDICT(OFS_PARM0);
2227 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2229 // note: this (incorrectly) assumes it is a simple polygon
2230 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2231 if (pointnum < 0 || pointnum >= surface->num_vertices)
2233 // FIXME: implement rotation/scaling
2234 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2236 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
2237 // float SPA_POSITION = 0;
2238 // float SPA_S_AXIS = 1;
2239 // float SPA_T_AXIS = 2;
2240 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2241 // float SPA_TEXCOORDS0 = 4;
2242 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2243 // float SPA_LIGHTMAP0_COLOR = 6;
2244 static void VM_SV_getsurfacepointattribute(void)
2248 msurface_t *surface;
2252 VM_SAFEPARMCOUNT(4, VM_SV_getsurfacepoint);
2253 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2254 ed = PRVM_G_EDICT(OFS_PARM0);
2255 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2257 // note: this (incorrectly) assumes it is a simple polygon
2258 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2259 if (pointnum < 0 || pointnum >= surface->num_vertices)
2261 // FIXME: implement rotation/scaling
2262 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
2264 switch( attributetype ) {
2265 // float SPA_POSITION = 0;
2267 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2269 // float SPA_S_AXIS = 1;
2271 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2273 // float SPA_T_AXIS = 2;
2275 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2277 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2279 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2281 // float SPA_TEXCOORDS0 = 4;
2283 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2284 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
2285 ret[0] = texcoord[0];
2286 ret[1] = texcoord[1];
2290 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2292 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2293 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
2294 ret[0] = texcoord[0];
2295 ret[1] = texcoord[1];
2299 // float SPA_LIGHTMAP0_COLOR = 6;
2301 // ignore alpha for now..
2302 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2305 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2309 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2310 static void VM_SV_getsurfacenormal(void)
2313 msurface_t *surface;
2315 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal);
2316 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2317 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2319 // FIXME: implement rotation/scaling
2320 // note: this (incorrectly) assumes it is a simple polygon
2321 // note: this only returns the first triangle, so it doesn't work very
2322 // well for curved surfaces or arbitrary meshes
2323 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);
2324 VectorNormalize(normal);
2325 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2327 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2328 static void VM_SV_getsurfacetexture(void)
2331 msurface_t *surface;
2332 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture);
2333 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2334 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2336 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2338 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2339 static void VM_SV_getsurfacenearpoint(void)
2341 int surfacenum, best;
2343 vec_t dist, bestdist;
2346 msurface_t *surface;
2348 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint);
2349 PRVM_G_FLOAT(OFS_RETURN) = -1;
2350 ed = PRVM_G_EDICT(OFS_PARM0);
2351 point = PRVM_G_VECTOR(OFS_PARM1);
2353 if (!ed || ed->priv.server->free)
2355 model = getmodel(ed);
2356 if (!model || !model->num_surfaces)
2359 // FIXME: implement rotation/scaling
2360 VectorSubtract(point, ed->fields.server->origin, p);
2362 bestdist = 1000000000;
2363 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2365 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2366 // first see if the nearest point on the surface's box is closer than the previous match
2367 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2368 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2369 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2370 dist = VectorLength2(clipped);
2371 if (dist < bestdist)
2373 // it is, check the nearest point on the actual geometry
2374 clippointtosurface(model, surface, p, clipped);
2375 VectorSubtract(clipped, p, clipped);
2376 dist += VectorLength2(clipped);
2377 if (dist < bestdist)
2379 // that's closer too, store it as the best match
2385 PRVM_G_FLOAT(OFS_RETURN) = best;
2387 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2388 static void VM_SV_getsurfaceclippedpoint(void)
2392 msurface_t *surface;
2394 VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint);
2395 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2396 ed = PRVM_G_EDICT(OFS_PARM0);
2397 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2399 // FIXME: implement rotation/scaling
2400 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2401 clippointtosurface(model, surface, p, out);
2402 // FIXME: implement rotation/scaling
2403 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2406 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2407 //this function originally written by KrimZon, made shorter by LordHavoc
2408 static void VM_SV_clientcommand (void)
2410 client_t *temp_client;
2412 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2414 //find client for this entity
2415 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2416 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2418 Con_Print("PF_clientcommand: entity is not a client\n");
2422 temp_client = host_client;
2423 host_client = svs.clients + i;
2424 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2425 host_client = temp_client;
2428 //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)
2429 static void VM_SV_setattachment (void)
2431 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2432 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2433 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2437 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2439 if (e == prog->edicts)
2441 VM_Warning("setattachment: can not modify world entity\n");
2444 if (e->priv.server->free)
2446 VM_Warning("setattachment: can not modify free entity\n");
2450 if (tagentity == NULL)
2451 tagentity = prog->edicts;
2453 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2455 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2457 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2460 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2462 modelindex = (int)tagentity->fields.server->modelindex;
2463 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2465 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2467 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);
2470 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));
2474 /////////////////////////////////////////
2475 // DP_MD3_TAGINFO extension coded by VorteX
2477 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2482 i = (int)e->fields.server->modelindex;
2483 if (i < 1 || i >= MAX_MODELS)
2485 model = sv.models[i];
2487 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2490 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2492 float scale = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale)->_float;
2496 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);
2498 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);
2501 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2507 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2508 && (model = sv.models[(int)ent->fields.server->modelindex])
2509 && model->animscenes)
2511 // if model has wrong frame, engine automatically switches to model first frame
2512 frame = (int)ent->fields.server->frame;
2513 if (frame < 0 || frame >= model->numframes)
2515 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2517 *out = identitymatrix;
2521 // Warnings/errors code:
2522 // 0 - normal (everything all-right)
2525 // 3 - null or non-precached model
2526 // 4 - no tags with requested index
2527 // 5 - runaway loop at attachment chain
2528 extern cvar_t cl_bob;
2529 extern cvar_t cl_bobcycle;
2530 extern cvar_t cl_bobup;
2531 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2535 int modelindex, attachloop;
2536 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2539 *out = identitymatrix; // warnings and errors return identical matrix
2541 if (ent == prog->edicts)
2543 if (ent->priv.server->free)
2546 modelindex = (int)ent->fields.server->modelindex;
2547 if (modelindex <= 0 || modelindex > MAX_MODELS)
2550 model = sv.models[modelindex];
2552 tagmatrix = identitymatrix;
2553 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2557 if (attachloop >= 256) // prevent runaway looping
2559 // apply transformation by child's tagindex on parent entity and then
2560 // by parent entity itself
2561 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2562 if (ret && attachloop == 0)
2564 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2565 SV_GetEntityMatrix(ent, &entitymatrix, false);
2566 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2567 // next iteration we process the parent entity
2568 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2570 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2571 ent = PRVM_EDICT_NUM(val->edict);
2578 // RENDER_VIEWMODEL magic
2579 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2581 Matrix4x4_Copy(&tagmatrix, out);
2582 ent = PRVM_EDICT_NUM(val->edict);
2584 SV_GetEntityMatrix(ent, &entitymatrix, true);
2585 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2588 // Cl_bob, ported from rendering code
2589 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2592 // LordHavoc: this code is *weird*, but not replacable (I think it
2593 // should be done in QC on the server, but oh well, quake is quake)
2594 // LordHavoc: figured out bobup: the time at which the sin is at 180
2595 // degrees (which allows lengthening or squishing the peak or valley)
2596 cycle = sv.time/cl_bobcycle.value;
2597 cycle -= (int)cycle;
2598 if (cycle < cl_bobup.value)
2599 cycle = sin(M_PI * cycle / cl_bobup.value);
2601 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2602 // bob is proportional to velocity in the xy plane
2603 // (don't count Z, or jumping messes it up)
2604 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;
2605 bob = bob*0.3 + bob*0.7*cycle;
2606 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2613 //float(entity ent, string tagname) gettagindex;
2615 static void VM_SV_gettagindex (void)
2618 const char *tag_name;
2619 int modelindex, tag_index;
2621 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2623 ent = PRVM_G_EDICT(OFS_PARM0);
2624 tag_name = PRVM_G_STRING(OFS_PARM1);
2626 if (ent == prog->edicts)
2628 VM_Warning("gettagindex: can't affect world entity\n");
2631 if (ent->priv.server->free)
2633 VM_Warning("gettagindex: can't affect free entity\n");
2637 modelindex = (int)ent->fields.server->modelindex;
2639 if (modelindex <= 0 || modelindex > MAX_MODELS)
2640 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2643 tag_index = SV_GetTagIndex(ent, tag_name);
2645 if(developer.integer >= 100)
2646 Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2648 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2651 //vector(entity ent, float tagindex) gettaginfo;
2652 static void VM_SV_gettaginfo (void)
2656 matrix4x4_t tag_matrix;
2659 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2661 e = PRVM_G_EDICT(OFS_PARM0);
2662 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2664 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2665 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2670 VM_Warning("gettagindex: can't affect world entity\n");
2673 VM_Warning("gettagindex: can't affect free entity\n");
2676 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2679 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2682 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2687 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2688 static void VM_SV_dropclient (void)
2691 client_t *oldhostclient;
2692 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2693 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2694 if (clientnum < 0 || clientnum >= svs.maxclients)
2696 VM_Warning("dropclient: not a client\n");
2699 if (!svs.clients[clientnum].active)
2701 VM_Warning("dropclient: that client slot is not connected\n");
2704 oldhostclient = host_client;
2705 host_client = svs.clients + clientnum;
2706 SV_DropClient(false);
2707 host_client = oldhostclient;
2710 //entity() spawnclient (DP_SV_BOTCLIENT)
2711 static void VM_SV_spawnclient (void)
2715 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2716 prog->xfunction->builtinsprofile += 2;
2718 for (i = 0;i < svs.maxclients;i++)
2720 if (!svs.clients[i].active)
2722 prog->xfunction->builtinsprofile += 100;
2723 SV_ConnectClient (i, NULL);
2724 // this has to be set or else ClientDisconnect won't be called
2725 // we assume the qc will call ClientConnect...
2726 svs.clients[i].clientconnectcalled = true;
2727 ed = PRVM_EDICT_NUM(i + 1);
2731 VM_RETURN_EDICT(ed);
2734 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2735 static void VM_SV_clienttype (void)
2738 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2739 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2740 if (clientnum < 0 || clientnum >= svs.maxclients)
2741 PRVM_G_FLOAT(OFS_RETURN) = 3;
2742 else if (!svs.clients[clientnum].active)
2743 PRVM_G_FLOAT(OFS_RETURN) = 0;
2744 else if (svs.clients[clientnum].netconnection)
2745 PRVM_G_FLOAT(OFS_RETURN) = 1;
2747 PRVM_G_FLOAT(OFS_RETURN) = 2;
2754 string(string key) serverkey
2757 void VM_SV_serverkey(void)
2759 char string[VM_STRINGTEMP_LENGTH];
2760 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2761 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2762 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2765 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2766 static void VM_SV_setmodelindex (void)
2771 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2773 e = PRVM_G_EDICT(OFS_PARM0);
2774 if (e == prog->edicts)
2776 VM_Warning("setmodelindex: can not modify world entity\n");
2779 if (e->priv.server->free)
2781 VM_Warning("setmodelindex: can not modify free entity\n");
2784 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2785 if (i <= 0 || i > MAX_MODELS)
2787 VM_Warning("setmodelindex: invalid modelindex\n");
2790 if (!sv.model_precache[i][0])
2792 VM_Warning("setmodelindex: model not precached\n");
2796 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2797 e->fields.server->modelindex = i;
2803 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2804 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2806 SetMinMaxSize (e, quakemins, quakemaxs, true);
2809 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2812 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2813 static void VM_SV_modelnameforindex (void)
2816 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2818 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2820 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2821 if (i <= 0 || i > MAX_MODELS)
2823 VM_Warning("modelnameforindex: invalid modelindex\n");
2826 if (!sv.model_precache[i][0])
2828 VM_Warning("modelnameforindex: model not precached\n");
2832 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2835 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2836 static void VM_SV_particleeffectnum (void)
2839 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2840 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2843 PRVM_G_FLOAT(OFS_RETURN) = i;
2846 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2847 static void VM_SV_trailparticles (void)
2849 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2851 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2854 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2855 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2856 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2857 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2858 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2859 SV_FlushBroadcastMessages();
2862 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2863 static void VM_SV_pointparticles (void)
2865 int effectnum, count;
2867 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2869 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2872 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2873 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2874 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2875 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2876 if (count == 1 && !VectorLength2(vel))
2879 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2880 MSG_WriteShort(&sv.datagram, effectnum);
2881 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2885 // 1+2+12+12+2=29 bytes
2886 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2887 MSG_WriteShort(&sv.datagram, effectnum);
2888 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2889 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2890 MSG_WriteShort(&sv.datagram, count);
2893 SV_FlushBroadcastMessages();
2896 prvm_builtin_t vm_sv_builtins[] = {
2897 NULL, // #0 NULL function (not callable) (QUAKE)
2898 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
2899 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
2900 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
2901 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
2902 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
2903 VM_break, // #6 void() break (QUAKE)
2904 VM_random, // #7 float() random (QUAKE)
2905 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
2906 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
2907 VM_error, // #10 void(string e) error (QUAKE)
2908 VM_objerror, // #11 void(string e) objerror (QUAKE)
2909 VM_vlen, // #12 float(vector v) vlen (QUAKE)
2910 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
2911 VM_spawn, // #14 entity() spawn (QUAKE)
2912 VM_remove, // #15 void(entity e) remove (QUAKE)
2913 VM_SV_traceline, // #16 float(vector v1, vector v2, float tryents) traceline (QUAKE)
2914 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
2915 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
2916 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
2917 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
2918 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
2919 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
2920 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
2921 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
2922 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
2923 VM_ftos, // #26 string(float f) ftos (QUAKE)
2924 VM_vtos, // #27 string(vector v) vtos (QUAKE)
2925 VM_coredump, // #28 void() coredump (QUAKE)
2926 VM_traceon, // #29 void() traceon (QUAKE)
2927 VM_traceoff, // #30 void() traceoff (QUAKE)
2928 VM_eprint, // #31 void(entity e) eprint (QUAKE)
2929 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
2930 NULL, // #33 (QUAKE)
2931 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
2932 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
2933 VM_rint, // #36 float(float v) rint (QUAKE)
2934 VM_floor, // #37 float(float v) floor (QUAKE)
2935 VM_ceil, // #38 float(float v) ceil (QUAKE)
2936 NULL, // #39 (QUAKE)
2937 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
2938 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
2939 NULL, // #42 (QUAKE)
2940 VM_fabs, // #43 float(float f) fabs (QUAKE)
2941 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
2942 VM_cvar, // #45 float(string s) cvar (QUAKE)
2943 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
2944 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
2945 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
2946 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
2947 NULL, // #50 (QUAKE)
2948 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
2949 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
2950 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
2951 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
2952 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
2953 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
2954 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
2955 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
2956 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
2957 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
2958 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
2959 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
2960 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
2961 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
2962 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
2963 NULL, // #66 (QUAKE)
2964 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
2965 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
2966 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
2967 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
2968 NULL, // #71 (QUAKE)
2969 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
2970 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
2971 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
2972 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
2973 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
2974 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
2975 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
2976 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
2977 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
2978 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2979 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
2980 NULL, // #83 (QUAKE)
2981 NULL, // #84 (QUAKE)
2982 NULL, // #85 (QUAKE)
2983 NULL, // #86 (QUAKE)
2984 NULL, // #87 (QUAKE)
2985 NULL, // #88 (QUAKE)
2986 NULL, // #89 (QUAKE)
2987 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2988 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2989 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2990 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2991 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2992 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2993 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2994 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2995 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2996 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2997 // FrikaC and Telejano range #100-#199
3008 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3009 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3010 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3011 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3012 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3013 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3014 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3015 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3016 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3017 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3098 // FTEQW range #200-#299
3117 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3120 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3121 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3122 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3123 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3124 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3125 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3126 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3127 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3128 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3129 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3131 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3199 // CSQC range #300-#399
3200 NULL, // #300 void() clearscene (EXT_CSQC)
3201 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3202 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3203 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3204 NULL, // #304 void() renderscene (EXT_CSQC)
3205 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3206 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3207 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3208 NULL, // #308 void() R_EndPolygon
3210 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3211 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3215 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3216 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3217 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3218 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3219 NULL, // #319 void(string name) freepic (EXT_CSQC)
3220 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3221 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3222 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3223 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3224 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3225 NULL, // #325 void(void) drawresetcliparea
3230 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3231 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3232 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3233 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3234 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3235 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3236 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3237 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3238 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3239 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3240 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3241 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3242 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3243 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3244 NULL, // #344 vector() getmousepos (EXT_CSQC)
3245 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3246 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3247 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3248 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3249 NULL, // #349 float() isdemo (EXT_CSQC)
3250 VM_isserver, // #350 float() isserver (EXT_CSQC)
3251 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3252 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3253 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3254 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3260 NULL, // #360 float() readbyte (EXT_CSQC)
3261 NULL, // #361 float() readchar (EXT_CSQC)
3262 NULL, // #362 float() readshort (EXT_CSQC)
3263 NULL, // #363 float() readlong (EXT_CSQC)
3264 NULL, // #364 float() readcoord (EXT_CSQC)
3265 NULL, // #365 float() readangle (EXT_CSQC)
3266 NULL, // #366 string() readstring (EXT_CSQC)
3267 NULL, // #367 float() readfloat (EXT_CSQC)
3300 // LordHavoc's range #400-#499
3301 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3302 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3303 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3304 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3305 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3306 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3307 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3308 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3309 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)
3310 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3311 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3312 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3313 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3314 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3315 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3316 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3317 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3318 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3319 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3320 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3321 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3322 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3323 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3324 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3325 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3326 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3327 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3328 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3329 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3330 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3331 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3332 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3333 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3334 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3335 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3336 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3337 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3338 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3339 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3340 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3341 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3342 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3343 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3344 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3345 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3346 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3347 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3348 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3349 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3350 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3351 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3352 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3353 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3354 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3355 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3356 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3357 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3358 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3360 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3361 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3362 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3363 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3364 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3365 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3366 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3367 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3368 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3369 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3370 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3372 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3373 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3374 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3375 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3376 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3377 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3378 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3379 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3380 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3381 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3382 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3383 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3384 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3385 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3386 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3387 VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3395 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3396 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3397 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3398 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3399 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3400 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3401 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3402 VM_SV_WritePicture, // #501
3404 VM_whichpack, // #503 string(string) whichpack = #503;
3411 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3412 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3413 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3423 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3425 void VM_SV_Cmd_Init(void)
3430 void VM_SV_Cmd_Reset(void)
3432 if(prog->funcoffsets.SV_Shutdown)
3434 func_t s = prog->funcoffsets.SV_Shutdown;
3435 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3436 PRVM_ExecuteProgram(s,"SV_Shutdown() required");