5 //============================================================================
10 char *vm_sv_extensions =
15 "DP_CON_ALIASPARAMETERS "
34 "DP_ENT_CUSTOMCOLORMAP "
35 "DP_ENT_EXTERIORMODELTOCLIENT "
37 "DP_ENT_LOWPRECISION "
41 "DP_GFX_EXTERNALTEXTURES "
42 "DP_GFX_EXTERNALTEXTURES_PERMAP "
44 "DP_GFX_QUAKE3MODELTAGS "
48 "DP_HALFLIFE_MAP_CVAR "
54 "DP_MOVETYPEBOUNCEMISSILE "
56 "DP_QC_ASINACOSATANATAN2TAN "
61 "DP_QC_CVAR_DEFSTRING "
67 "DP_QC_FINDCHAINFLAGS "
68 "DP_QC_FINDCHAINFLOAT "
74 "DP_QC_GETSURFACEPOINTATTRIBUTE "
77 "DP_QC_MULTIPLETEMPSTRINGS "
78 "DP_QC_NUM_FOR_EDICT "
80 "DP_QC_SINCOSSQRTPOW "
82 "DP_QC_STRINGBUFFERS "
83 "DP_QC_STRINGCOLORFUNCTIONS "
84 "DP_QC_STRING_CASE_FUNCTIONS "
86 "DP_QC_TOKENIZEBYSEPARATOR "
89 "DP_QC_TRACE_MOVETYPE_HITMODEL "
90 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
91 "DP_QC_UNLIMITEDTEMPSTRINGS "
93 "DP_QC_VECTOANGLES_WITH_ROLL "
94 "DP_QC_VECTORVECTORS "
100 "DP_SND_DIRECTIONLESSATTNNONE "
107 "DP_SV_CLIENTCOLORS "
110 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
111 "DP_SV_DRAWONLYTOCLIENT "
114 "DP_SV_ENTITYCONTENTSTRANSITION "
115 "DP_SV_MODELFLAGS_AS_EFFECTS "
116 "DP_SV_MOVETYPESTEP_LANDEVENT "
118 "DP_SV_NODRAWTOCLIENT "
119 "DP_SV_ONENTITYNOSPAWNFUNCTION "
121 "DP_SV_PLAYERPHYSICS "
122 "DP_SV_POINTPARTICLES "
124 "DP_SV_PRECACHEANYTIME "
127 "DP_SV_ROTATINGBMODEL "
131 "DP_SV_SPAWNFUNC_PREFIX "
132 "DP_SV_WRITEUNTERMINATEDSTRING "
136 "DP_TE_EXPLOSIONRGB "
138 "DP_TE_PARTICLECUBE "
139 "DP_TE_PARTICLERAIN "
140 "DP_TE_PARTICLESNOW "
142 "DP_TE_QUADEFFECTS1 "
145 "DP_TE_STANDARDEFFECTBUILTINS "
146 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
151 "KRIMZON_SV_PARSECLIENTCOMMAND "
154 "NEXUIZ_PLAYERMODEL "
156 "PRYDON_CLIENTCURSOR "
157 "TENEBRAE_GFX_DLIGHTS "
159 //"EXT_CSQC " // not ready yet
166 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.
168 setorigin (entity, origin)
171 static void VM_SV_setorigin (void)
176 VM_SAFEPARMCOUNT(2, VM_setorigin);
178 e = PRVM_G_EDICT(OFS_PARM0);
179 if (e == prog->edicts)
181 VM_Warning("setorigin: can not modify world entity\n");
184 if (e->priv.server->free)
186 VM_Warning("setorigin: can not modify free entity\n");
189 org = PRVM_G_VECTOR(OFS_PARM1);
190 VectorCopy (org, e->fields.server->origin);
191 SV_LinkEdict (e, false);
194 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
195 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
199 for (i=0 ; i<3 ; i++)
201 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
203 // set derived values
204 VectorCopy (min, e->fields.server->mins);
205 VectorCopy (max, e->fields.server->maxs);
206 VectorSubtract (max, min, e->fields.server->size);
208 SV_LinkEdict (e, false);
215 the size box is rotated by the current angle
216 LordHavoc: no it isn't...
218 setsize (entity, minvector, maxvector)
221 static void VM_SV_setsize (void)
226 VM_SAFEPARMCOUNT(3, VM_setsize);
228 e = PRVM_G_EDICT(OFS_PARM0);
229 if (e == prog->edicts)
231 VM_Warning("setsize: can not modify world entity\n");
234 if (e->priv.server->free)
236 VM_Warning("setsize: can not modify free entity\n");
239 min = PRVM_G_VECTOR(OFS_PARM1);
240 max = PRVM_G_VECTOR(OFS_PARM2);
241 SetMinMaxSize (e, min, max, false);
249 setmodel(entity, model)
252 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
253 static void VM_SV_setmodel (void)
259 VM_SAFEPARMCOUNT(2, VM_setmodel);
261 e = PRVM_G_EDICT(OFS_PARM0);
262 if (e == prog->edicts)
264 VM_Warning("setmodel: can not modify world entity\n");
267 if (e->priv.server->free)
269 VM_Warning("setmodel: can not modify free entity\n");
272 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
273 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
274 e->fields.server->modelindex = i;
280 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
281 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
283 SetMinMaxSize (e, quakemins, quakemaxs, true);
286 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
293 single print to a specific client
295 sprint(clientent, value)
298 static void VM_SV_sprint (void)
302 char string[VM_STRINGTEMP_LENGTH];
304 VM_VarString(1, string, sizeof(string));
306 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
308 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
309 // LordHavoc: div0 requested that sprintto world operate like print
316 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
318 VM_Warning("tried to centerprint to a non-client\n");
322 client = svs.clients + entnum-1;
323 if (!client->netconnection)
326 MSG_WriteChar(&client->netconnection->message,svc_print);
327 MSG_WriteString(&client->netconnection->message, string);
335 single print to a specific client
337 centerprint(clientent, value)
340 static void VM_SV_centerprint (void)
344 char string[VM_STRINGTEMP_LENGTH];
346 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
348 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
350 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
352 VM_Warning("tried to centerprint to a non-client\n");
356 client = svs.clients + entnum-1;
357 if (!client->netconnection)
360 VM_VarString(1, string, sizeof(string));
361 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
362 MSG_WriteString(&client->netconnection->message, string);
369 particle(origin, color, count)
372 static void VM_SV_particle (void)
378 VM_SAFEPARMCOUNT(4, VM_SV_particle);
380 org = PRVM_G_VECTOR(OFS_PARM0);
381 dir = PRVM_G_VECTOR(OFS_PARM1);
382 color = PRVM_G_FLOAT(OFS_PARM2);
383 count = PRVM_G_FLOAT(OFS_PARM3);
384 SV_StartParticle (org, dir, (int)color, (int)count);
394 static void VM_SV_ambientsound (void)
398 float vol, attenuation;
401 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
403 pos = PRVM_G_VECTOR (OFS_PARM0);
404 samp = PRVM_G_STRING(OFS_PARM1);
405 vol = PRVM_G_FLOAT(OFS_PARM2);
406 attenuation = PRVM_G_FLOAT(OFS_PARM3);
408 // check to see if samp was properly precached
409 soundnum = SV_SoundIndex(samp, 1);
417 // add an svc_spawnambient command to the level signon packet
420 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
422 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
424 MSG_WriteVector(&sv.signon, pos, sv.protocol);
426 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
427 MSG_WriteShort (&sv.signon, soundnum);
429 MSG_WriteByte (&sv.signon, soundnum);
431 MSG_WriteByte (&sv.signon, (int)(vol*255));
432 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
440 Each entity can have eight independant sound sources, like voice,
443 Channel 0 is an auto-allocate channel, the others override anything
444 already running on that entity/channel pair.
446 An attenuation of 0 will play full volume everywhere in the level.
447 Larger attenuations will drop off.
451 static void VM_SV_sound (void)
455 prvm_edict_t *entity;
459 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
461 entity = PRVM_G_EDICT(OFS_PARM0);
462 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
463 sample = PRVM_G_STRING(OFS_PARM2);
464 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
465 attenuation = PRVM_G_FLOAT(OFS_PARM4);
468 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
472 if (volume < 0 || volume > 255)
474 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
478 if (attenuation < 0 || attenuation > 4)
480 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
484 if (channel < 0 || channel > 7)
486 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
490 SV_StartSound (entity, channel, sample, volume, attenuation);
497 Follows the same logic as VM_SV_sound, except instead of
498 an entity, an origin for the sound is provided, and channel
499 is omitted (since no entity is being tracked).
503 static void VM_SV_pointsound(void)
510 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
512 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
513 sample = PRVM_G_STRING(OFS_PARM1);
514 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
515 attenuation = PRVM_G_FLOAT(OFS_PARM3);
517 if (volume < 0 || volume > 255)
519 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
523 if (attenuation < 0 || attenuation > 4)
525 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
529 SV_StartPointSound (org, sample, volume, attenuation);
536 Used for use tracing and shot targeting
537 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
538 if the tryents flag is set.
540 traceline (vector1, vector2, movetype, ignore)
543 static void VM_SV_traceline (void)
550 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
552 prog->xfunction->builtinsprofile += 30;
554 v1 = PRVM_G_VECTOR(OFS_PARM0);
555 v2 = PRVM_G_VECTOR(OFS_PARM1);
556 move = (int)PRVM_G_FLOAT(OFS_PARM2);
557 ent = PRVM_G_EDICT(OFS_PARM3);
559 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]))
560 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));
562 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
564 VM_SetTraceGlobals(&trace);
572 Used for use tracing and shot targeting
573 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
574 if the tryents flag is set.
576 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
579 // LordHavoc: added this for my own use, VERY useful, similar to traceline
580 static void VM_SV_tracebox (void)
582 float *v1, *v2, *m1, *m2;
587 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
589 prog->xfunction->builtinsprofile += 30;
591 v1 = PRVM_G_VECTOR(OFS_PARM0);
592 m1 = PRVM_G_VECTOR(OFS_PARM1);
593 m2 = PRVM_G_VECTOR(OFS_PARM2);
594 v2 = PRVM_G_VECTOR(OFS_PARM3);
595 move = (int)PRVM_G_FLOAT(OFS_PARM4);
596 ent = PRVM_G_EDICT(OFS_PARM5);
598 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]))
599 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));
601 trace = SV_Move (v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
603 VM_SetTraceGlobals(&trace);
606 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
611 vec3_t original_origin;
612 vec3_t original_velocity;
613 vec3_t original_angles;
614 vec3_t original_avelocity;
618 VectorCopy(tossent->fields.server->origin , original_origin );
619 VectorCopy(tossent->fields.server->velocity , original_velocity );
620 VectorCopy(tossent->fields.server->angles , original_angles );
621 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
623 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
624 if (val != NULL && val->_float != 0)
625 gravity = val->_float;
628 gravity *= sv_gravity.value * 0.05;
630 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
632 SV_CheckVelocity (tossent);
633 tossent->fields.server->velocity[2] -= gravity;
634 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
635 VectorScale (tossent->fields.server->velocity, 0.05, move);
636 VectorAdd (tossent->fields.server->origin, move, end);
637 trace = SV_Move (tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
638 VectorCopy (trace.endpos, tossent->fields.server->origin);
640 if (trace.fraction < 1)
644 VectorCopy(original_origin , tossent->fields.server->origin );
645 VectorCopy(original_velocity , tossent->fields.server->velocity );
646 VectorCopy(original_angles , tossent->fields.server->angles );
647 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
652 static void VM_SV_tracetoss (void)
656 prvm_edict_t *ignore;
658 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
660 prog->xfunction->builtinsprofile += 600;
662 ent = PRVM_G_EDICT(OFS_PARM0);
663 if (ent == prog->edicts)
665 VM_Warning("tracetoss: can not use world entity\n");
668 ignore = PRVM_G_EDICT(OFS_PARM1);
670 trace = SV_Trace_Toss (ent, ignore);
672 VM_SetTraceGlobals(&trace);
675 //============================================================================
677 static int checkpvsbytes;
678 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
680 static int VM_SV_newcheckclient (int check)
686 // cycle to the next one
688 check = bound(1, check, svs.maxclients);
689 if (check == svs.maxclients)
697 prog->xfunction->builtinsprofile++;
699 if (i == svs.maxclients+1)
701 // look up the client's edict
702 ent = PRVM_EDICT_NUM(i);
703 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
704 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
706 // found a valid client (possibly the same one again)
710 // get the PVS for the entity
711 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
713 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
714 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
723 Returns a client (or object that has a client enemy) that would be a
726 If there is more than one valid option, they are cycled each frame
728 If (self.origin + self.viewofs) is not in the PVS of the current target,
729 it is not returned at all.
734 int c_invis, c_notvis;
735 static void VM_SV_checkclient (void)
737 prvm_edict_t *ent, *self;
740 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
742 // find a new check if on a new frame
743 if (sv.time - sv.lastchecktime >= 0.1)
745 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
746 sv.lastchecktime = sv.time;
749 // return check if it might be visible
750 ent = PRVM_EDICT_NUM(sv.lastcheck);
751 if (ent->priv.server->free || ent->fields.server->health <= 0)
753 VM_RETURN_EDICT(prog->edicts);
757 // if current entity can't possibly see the check entity, return 0
758 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
759 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
760 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
763 VM_RETURN_EDICT(prog->edicts);
767 // might be able to see it
769 VM_RETURN_EDICT(ent);
772 //============================================================================
779 Sends text over to the client's execution buffer
781 stuffcmd (clientent, value, ...)
784 static void VM_SV_stuffcmd (void)
788 char string[VM_STRINGTEMP_LENGTH];
790 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
792 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
793 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
795 VM_Warning("Can't stuffcmd to a non-client\n");
799 VM_VarString(1, string, sizeof(string));
802 host_client = svs.clients + entnum-1;
803 Host_ClientCommands ("%s", string);
811 Returns a chain of entities that have origins within a spherical area
813 findradius (origin, radius)
816 static void VM_SV_findradius (void)
818 prvm_edict_t *ent, *chain;
819 vec_t radius, radius2;
820 vec3_t org, eorg, mins, maxs;
823 prvm_edict_t *touchedicts[MAX_EDICTS];
825 VM_SAFEPARMCOUNT(2, VM_SV_findradius);
827 chain = (prvm_edict_t *)prog->edicts;
829 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
830 radius = PRVM_G_FLOAT(OFS_PARM1);
831 radius2 = radius * radius;
833 mins[0] = org[0] - (radius + 1);
834 mins[1] = org[1] - (radius + 1);
835 mins[2] = org[2] - (radius + 1);
836 maxs[0] = org[0] + (radius + 1);
837 maxs[1] = org[1] + (radius + 1);
838 maxs[2] = org[2] + (radius + 1);
839 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
840 if (numtouchedicts > MAX_EDICTS)
842 // this never happens
843 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
844 numtouchedicts = MAX_EDICTS;
846 for (i = 0;i < numtouchedicts;i++)
848 ent = touchedicts[i];
849 prog->xfunction->builtinsprofile++;
850 // Quake did not return non-solid entities but darkplaces does
851 // (note: this is the reason you can't blow up fallen zombies)
852 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
854 // LordHavoc: compare against bounding box rather than center so it
855 // doesn't miss large objects, and use DotProduct instead of Length
856 // for a major speedup
857 VectorSubtract(org, ent->fields.server->origin, eorg);
858 if (sv_gameplayfix_findradiusdistancetobox.integer)
860 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
861 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
862 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
865 VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
866 if (DotProduct(eorg, eorg) < radius2)
868 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
873 VM_RETURN_EDICT(chain);
876 static void VM_SV_precache_sound (void)
878 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
879 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
882 static void VM_SV_precache_model (void)
884 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
885 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
886 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
893 float(float yaw, float dist[, settrace]) walkmove
896 static void VM_SV_walkmove (void)
905 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
907 // assume failure if it returns early
908 PRVM_G_FLOAT(OFS_RETURN) = 0;
910 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
911 if (ent == prog->edicts)
913 VM_Warning("walkmove: can not modify world entity\n");
916 if (ent->priv.server->free)
918 VM_Warning("walkmove: can not modify free entity\n");
921 yaw = PRVM_G_FLOAT(OFS_PARM0);
922 dist = PRVM_G_FLOAT(OFS_PARM1);
923 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
925 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
928 yaw = yaw*M_PI*2 / 360;
930 move[0] = cos(yaw)*dist;
931 move[1] = sin(yaw)*dist;
934 // save program state, because SV_movestep may call other progs
935 oldf = prog->xfunction;
936 oldself = prog->globals.server->self;
938 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
941 // restore program state
942 prog->xfunction = oldf;
943 prog->globals.server->self = oldself;
953 static void VM_SV_droptofloor (void)
959 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
961 // assume failure if it returns early
962 PRVM_G_FLOAT(OFS_RETURN) = 0;
964 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
965 if (ent == prog->edicts)
967 VM_Warning("droptofloor: can not modify world entity\n");
970 if (ent->priv.server->free)
972 VM_Warning("droptofloor: can not modify free entity\n");
976 VectorCopy (ent->fields.server->origin, end);
979 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
980 SV_UnstickEntity(ent);
982 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
983 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
986 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]);
987 VectorAdd(ent->fields.server->origin, offset, org);
988 trace = SV_Move (org, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
989 VectorSubtract(trace.endpos, offset, trace.endpos);
990 if (trace.startsolid)
992 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]);
993 SV_UnstickEntity(ent);
994 SV_LinkEdict (ent, false);
995 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
996 ent->fields.server->groundentity = 0;
997 PRVM_G_FLOAT(OFS_RETURN) = 1;
999 else if (trace.fraction < 1)
1001 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]);
1002 VectorCopy (trace.endpos, ent->fields.server->origin);
1003 SV_UnstickEntity(ent);
1004 SV_LinkEdict (ent, false);
1005 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1006 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1007 PRVM_G_FLOAT(OFS_RETURN) = 1;
1008 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1009 ent->priv.server->suspendedinairflag = true;
1014 if (trace.fraction != 1)
1016 if (trace.fraction < 1)
1017 VectorCopy (trace.endpos, ent->fields.server->origin);
1018 SV_LinkEdict (ent, false);
1019 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1020 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1021 PRVM_G_FLOAT(OFS_RETURN) = 1;
1022 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1023 ent->priv.server->suspendedinairflag = true;
1032 void(float style, string value) lightstyle
1035 static void VM_SV_lightstyle (void)
1042 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1044 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1045 val = PRVM_G_STRING(OFS_PARM1);
1047 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1048 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1051 // change the string in sv
1052 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1054 // send message to all clients on this server
1055 if (sv.state != ss_active)
1058 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1060 if (client->active && client->netconnection)
1062 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1063 MSG_WriteChar (&client->netconnection->message,style);
1064 MSG_WriteString (&client->netconnection->message, val);
1074 static void VM_SV_checkbottom (void)
1076 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1077 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1085 static void VM_SV_pointcontents (void)
1087 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1088 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1095 Pick a vector for the player to shoot along
1096 vector aim(entity, missilespeed)
1099 static void VM_SV_aim (void)
1101 prvm_edict_t *ent, *check, *bestent;
1102 vec3_t start, dir, end, bestdir;
1105 float dist, bestdist;
1108 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1110 // assume failure if it returns early
1111 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1112 // if sv_aim is so high it can't possibly accept anything, skip out early
1113 if (sv_aim.value >= 1)
1116 ent = PRVM_G_EDICT(OFS_PARM0);
1117 if (ent == prog->edicts)
1119 VM_Warning("aim: can not use world entity\n");
1122 if (ent->priv.server->free)
1124 VM_Warning("aim: can not use free entity\n");
1127 speed = PRVM_G_FLOAT(OFS_PARM1);
1129 VectorCopy (ent->fields.server->origin, start);
1132 // try sending a trace straight
1133 VectorCopy (prog->globals.server->v_forward, dir);
1134 VectorMA (start, 2048, dir, end);
1135 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1136 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1137 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1139 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1144 // try all possible entities
1145 VectorCopy (dir, bestdir);
1146 bestdist = sv_aim.value;
1149 check = PRVM_NEXT_EDICT(prog->edicts);
1150 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1152 prog->xfunction->builtinsprofile++;
1153 if (check->fields.server->takedamage != DAMAGE_AIM)
1157 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1158 continue; // don't aim at teammate
1159 for (j=0 ; j<3 ; j++)
1160 end[j] = check->fields.server->origin[j]
1161 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1162 VectorSubtract (end, start, dir);
1163 VectorNormalize (dir);
1164 dist = DotProduct (dir, prog->globals.server->v_forward);
1165 if (dist < bestdist)
1166 continue; // to far to turn
1167 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1168 if (tr.ent == check)
1169 { // can shoot at this one
1177 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1178 dist = DotProduct (dir, prog->globals.server->v_forward);
1179 VectorScale (prog->globals.server->v_forward, dist, end);
1181 VectorNormalize (end);
1182 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1186 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1191 ===============================================================================
1195 ===============================================================================
1198 #define MSG_BROADCAST 0 // unreliable to all
1199 #define MSG_ONE 1 // reliable to one (msg_entity)
1200 #define MSG_ALL 2 // reliable to all
1201 #define MSG_INIT 3 // write to the init string
1202 #define MSG_ENTITY 5
1204 sizebuf_t *WriteDest (void)
1210 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1214 return &sv.datagram;
1217 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1218 entnum = PRVM_NUM_FOR_EDICT(ent);
1219 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1221 VM_Warning ("WriteDest: tried to write to non-client\n");
1222 return &sv.reliable_datagram;
1225 return &svs.clients[entnum-1].netconnection->message;
1228 VM_Warning ("WriteDest: bad destination\n");
1230 return &sv.reliable_datagram;
1236 return sv.writeentitiestoclient_msg;
1242 static void VM_SV_WriteByte (void)
1244 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1245 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1248 static void VM_SV_WriteChar (void)
1250 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1251 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1254 static void VM_SV_WriteShort (void)
1256 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1257 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1260 static void VM_SV_WriteLong (void)
1262 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1263 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1266 static void VM_SV_WriteAngle (void)
1268 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1269 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1272 static void VM_SV_WriteCoord (void)
1274 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1275 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1278 static void VM_SV_WriteString (void)
1280 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1281 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1284 static void VM_SV_WriteUnterminatedString (void)
1286 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1287 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1291 static void VM_SV_WriteEntity (void)
1293 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1294 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1297 //////////////////////////////////////////////////////////
1299 static void VM_SV_makestatic (void)
1304 // allow 0 parameters due to an id1 qc bug in which this function is used
1305 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1306 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1308 if (prog->argc >= 1)
1309 ent = PRVM_G_EDICT(OFS_PARM0);
1311 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1312 if (ent == prog->edicts)
1314 VM_Warning("makestatic: can not modify world entity\n");
1317 if (ent->priv.server->free)
1319 VM_Warning("makestatic: can not modify free entity\n");
1324 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1329 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1330 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1331 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1333 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1335 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1336 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1337 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1341 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1342 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1343 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1346 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1347 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1348 for (i=0 ; i<3 ; i++)
1350 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1351 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1354 // throw the entity away now
1358 //=============================================================================
1365 static void VM_SV_setspawnparms (void)
1371 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1373 ent = PRVM_G_EDICT(OFS_PARM0);
1374 i = PRVM_NUM_FOR_EDICT(ent);
1375 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1377 Con_Print("tried to setspawnparms on a non-client\n");
1381 // copy spawn parms out of the client_t
1382 client = svs.clients + i-1;
1383 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1384 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1391 Returns a color vector indicating the lighting at the requested point.
1393 (Internal Operation note: actually measures the light beneath the point, just like
1394 the model lighting on the client)
1399 static void VM_SV_getlight (void)
1401 vec3_t ambientcolor, diffusecolor, diffusenormal;
1403 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1404 p = PRVM_G_VECTOR(OFS_PARM0);
1405 VectorClear(ambientcolor);
1406 VectorClear(diffusecolor);
1407 VectorClear(diffusenormal);
1408 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1409 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1410 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1415 unsigned char type; // 1/2/8 or other value if isn't used
1419 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1420 static int vm_customstats_last;
1422 void VM_CustomStats_Clear (void)
1426 Z_Free(vm_customstats);
1427 vm_customstats = NULL;
1428 vm_customstats_last = -1;
1432 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1440 for(i=0; i<vm_customstats_last+1 ;i++)
1442 if(!vm_customstats[i].type)
1444 switch(vm_customstats[i].type)
1446 //string as 16 bytes
1449 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1450 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1451 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1452 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1453 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1455 //float field sent as-is
1457 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1459 //integer value of float field
1461 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1469 // void(float index, float type, .void field) SV_AddStat = #232;
1470 // Set up an auto-sent player stat.
1471 // Client's get thier own fields sent to them. Index may not be less than 32.
1472 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1473 // 1: string (4 stats carrying a total of 16 charactures)
1474 // 2: float (one stat, float converted to an integer for transportation)
1475 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1476 static void VM_SV_AddStat (void)
1481 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1485 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1488 VM_Warning("PF_SV_AddStat: not enough memory\n");
1492 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1493 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1494 off = PRVM_G_INT (OFS_PARM2);
1499 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1502 if(i >= (MAX_CL_STATS-32))
1504 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1507 if(i > (MAX_CL_STATS-32-4) && type == 1)
1509 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1512 vm_customstats[i].type = type;
1513 vm_customstats[i].fieldoffset = off;
1514 if(vm_customstats_last < i)
1515 vm_customstats_last = i;
1522 copies data from one entity to another
1524 copyentity(src, dst)
1527 static void VM_SV_copyentity (void)
1529 prvm_edict_t *in, *out;
1530 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1531 in = PRVM_G_EDICT(OFS_PARM0);
1532 if (in == prog->edicts)
1534 VM_Warning("copyentity: can not read world entity\n");
1537 if (in->priv.server->free)
1539 VM_Warning("copyentity: can not read free entity\n");
1542 out = PRVM_G_EDICT(OFS_PARM1);
1543 if (out == prog->edicts)
1545 VM_Warning("copyentity: can not modify world entity\n");
1548 if (out->priv.server->free)
1550 VM_Warning("copyentity: can not modify free entity\n");
1553 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1554 SV_LinkEdict(out, false);
1562 sets the color of a client and broadcasts the update to all connected clients
1564 setcolor(clientent, value)
1567 static void VM_SV_setcolor (void)
1573 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1574 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1575 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1577 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1579 Con_Print("tried to setcolor a non-client\n");
1583 client = svs.clients + entnum-1;
1586 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1588 client->edict->fields.server->team = (i & 15) + 1;
1591 if (client->old_colors != client->colors)
1593 client->old_colors = client->colors;
1594 // send notification to all clients
1595 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1596 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1597 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1605 effect(origin, modelname, startframe, framecount, framerate)
1608 static void VM_SV_effect (void)
1612 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1613 s = PRVM_G_STRING(OFS_PARM1);
1616 VM_Warning("effect: no model specified\n");
1620 i = SV_ModelIndex(s, 1);
1623 VM_Warning("effect: model not precached\n");
1627 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1629 VM_Warning("effect: framecount < 1\n");
1633 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1635 VM_Warning("effect: framerate < 1\n");
1639 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));
1642 static void VM_SV_te_blood (void)
1644 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1645 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1647 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1648 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1650 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1651 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1652 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1654 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1655 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1656 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1658 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1659 SV_FlushBroadcastMessages();
1662 static void VM_SV_te_bloodshower (void)
1664 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1665 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1667 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1668 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1670 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1671 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1672 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1674 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1675 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1676 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1678 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1680 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1681 SV_FlushBroadcastMessages();
1684 static void VM_SV_te_explosionrgb (void)
1686 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1687 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1688 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1690 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1691 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1692 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1694 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1695 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1696 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1697 SV_FlushBroadcastMessages();
1700 static void VM_SV_te_particlecube (void)
1702 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1703 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1705 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1706 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
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_VECTOR(OFS_PARM2)[0], sv.protocol);
1717 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1718 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1720 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1722 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1723 // gravity true/false
1724 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1726 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1727 SV_FlushBroadcastMessages();
1730 static void VM_SV_te_particlerain (void)
1732 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1733 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1735 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1736 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1738 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1739 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1740 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1742 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1743 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1744 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1746 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1747 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1748 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1750 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1752 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1753 SV_FlushBroadcastMessages();
1756 static void VM_SV_te_particlesnow (void)
1758 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1759 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1761 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1762 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1764 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1765 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1766 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1768 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1769 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1770 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1772 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1773 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1774 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1776 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1778 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1779 SV_FlushBroadcastMessages();
1782 static void VM_SV_te_spark (void)
1784 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1785 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1787 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1788 MSG_WriteByte(&sv.datagram, TE_SPARK);
1790 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1791 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1792 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1794 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1795 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1796 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1798 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1799 SV_FlushBroadcastMessages();
1802 static void VM_SV_te_gunshotquad (void)
1804 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1805 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1806 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1808 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1809 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1810 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1811 SV_FlushBroadcastMessages();
1814 static void VM_SV_te_spikequad (void)
1816 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1817 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1818 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1820 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1821 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1822 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1823 SV_FlushBroadcastMessages();
1826 static void VM_SV_te_superspikequad (void)
1828 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1829 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1830 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1832 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1833 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1834 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1835 SV_FlushBroadcastMessages();
1838 static void VM_SV_te_explosionquad (void)
1840 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
1841 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1842 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1844 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1845 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1847 SV_FlushBroadcastMessages();
1850 static void VM_SV_te_smallflash (void)
1852 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
1853 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1854 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1856 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1857 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1858 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1859 SV_FlushBroadcastMessages();
1862 static void VM_SV_te_customflash (void)
1864 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
1865 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1867 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1868 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
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);
1874 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1876 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1878 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1879 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1880 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1881 SV_FlushBroadcastMessages();
1884 static void VM_SV_te_gunshot (void)
1886 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
1887 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1888 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1890 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1891 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1892 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1893 SV_FlushBroadcastMessages();
1896 static void VM_SV_te_spike (void)
1898 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
1899 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1900 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1905 SV_FlushBroadcastMessages();
1908 static void VM_SV_te_superspike (void)
1910 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
1911 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1912 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1914 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1915 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1916 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1917 SV_FlushBroadcastMessages();
1920 static void VM_SV_te_explosion (void)
1922 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
1923 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1924 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1926 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1929 SV_FlushBroadcastMessages();
1932 static void VM_SV_te_tarexplosion (void)
1934 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
1935 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1936 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1941 SV_FlushBroadcastMessages();
1944 static void VM_SV_te_wizspike (void)
1946 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
1947 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1948 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1950 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1952 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1953 SV_FlushBroadcastMessages();
1956 static void VM_SV_te_knightspike (void)
1958 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
1959 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1960 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1964 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1965 SV_FlushBroadcastMessages();
1968 static void VM_SV_te_lavasplash (void)
1970 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
1971 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1972 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1974 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1975 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1976 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1977 SV_FlushBroadcastMessages();
1980 static void VM_SV_te_teleport (void)
1982 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
1983 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1984 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1989 SV_FlushBroadcastMessages();
1992 static void VM_SV_te_explosion2 (void)
1994 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
1995 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1996 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1998 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1999 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2000 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2002 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2003 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2004 SV_FlushBroadcastMessages();
2007 static void VM_SV_te_lightning1 (void)
2009 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2010 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2011 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2013 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2015 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2016 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2017 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2019 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2020 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2021 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2022 SV_FlushBroadcastMessages();
2025 static void VM_SV_te_lightning2 (void)
2027 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2028 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2029 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2031 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2033 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2034 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2035 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2037 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2038 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2039 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2040 SV_FlushBroadcastMessages();
2043 static void VM_SV_te_lightning3 (void)
2045 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2046 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2047 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2049 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2052 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2055 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2056 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2058 SV_FlushBroadcastMessages();
2061 static void VM_SV_te_beam (void)
2063 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2064 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2065 MSG_WriteByte(&sv.datagram, TE_BEAM);
2067 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2069 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2070 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2071 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2074 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2075 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2076 SV_FlushBroadcastMessages();
2079 static void VM_SV_te_plasmaburn (void)
2081 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2082 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2083 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2084 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2085 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2086 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2087 SV_FlushBroadcastMessages();
2090 static void VM_SV_te_flamejet (void)
2092 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2093 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2094 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2096 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2097 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2098 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2100 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2101 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2102 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2104 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2105 SV_FlushBroadcastMessages();
2108 void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2111 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2113 bestdist = 1000000000;
2115 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2117 // clip original point to each triangle of the surface and find the
2118 // triangle that is closest
2119 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2120 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2121 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2122 TriangleNormal(v[0], v[1], v[2], facenormal);
2123 VectorNormalize(facenormal);
2124 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2125 VectorMA(p, offsetdist, facenormal, temp);
2126 for (j = 0, k = 2;j < 3;k = j, j++)
2128 VectorSubtract(v[k], v[j], edgenormal);
2129 CrossProduct(edgenormal, facenormal, sidenormal);
2130 VectorNormalize(sidenormal);
2131 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2133 VectorMA(temp, offsetdist, sidenormal, temp);
2135 dist = VectorDistance2(temp, p);
2136 if (bestdist > dist)
2139 VectorCopy(temp, out);
2144 static dp_model_t *getmodel(prvm_edict_t *ed)
2147 if (!ed || ed->priv.server->free)
2149 modelindex = (int)ed->fields.server->modelindex;
2150 if (modelindex < 1 || modelindex >= MAX_MODELS)
2152 return sv.models[modelindex];
2155 static msurface_t *getsurface(dp_model_t *model, int surfacenum)
2157 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2159 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2163 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2164 static void VM_SV_getsurfacenumpoints(void)
2167 msurface_t *surface;
2168 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints);
2169 // return 0 if no such surface
2170 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2172 PRVM_G_FLOAT(OFS_RETURN) = 0;
2176 // note: this (incorrectly) assumes it is a simple polygon
2177 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2179 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2180 static void VM_SV_getsurfacepoint(void)
2184 msurface_t *surface;
2186 VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint);
2187 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2188 ed = PRVM_G_EDICT(OFS_PARM0);
2189 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2191 // note: this (incorrectly) assumes it is a simple polygon
2192 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2193 if (pointnum < 0 || pointnum >= surface->num_vertices)
2195 // FIXME: implement rotation/scaling
2196 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2198 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
2199 // float SPA_POSITION = 0;
2200 // float SPA_S_AXIS = 1;
2201 // float SPA_T_AXIS = 2;
2202 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2203 // float SPA_TEXCOORDS0 = 4;
2204 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2205 // float SPA_LIGHTMAP0_COLOR = 6;
2206 static void VM_SV_getsurfacepointattribute(void)
2210 msurface_t *surface;
2214 VM_SAFEPARMCOUNT(4, VM_SV_getsurfacepoint);
2215 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2216 ed = PRVM_G_EDICT(OFS_PARM0);
2217 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2219 // note: this (incorrectly) assumes it is a simple polygon
2220 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2221 if (pointnum < 0 || pointnum >= surface->num_vertices)
2223 // FIXME: implement rotation/scaling
2224 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
2226 switch( attributetype ) {
2227 // float SPA_POSITION = 0;
2229 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2231 // float SPA_S_AXIS = 1;
2233 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2235 // float SPA_T_AXIS = 2;
2237 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2239 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2241 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2243 // float SPA_TEXCOORDS0 = 4;
2245 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2246 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
2247 ret[0] = texcoord[0];
2248 ret[1] = texcoord[1];
2252 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2254 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2255 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
2256 ret[0] = texcoord[0];
2257 ret[1] = texcoord[1];
2261 // float SPA_LIGHTMAP0_COLOR = 6;
2263 // ignore alpha for now..
2264 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2267 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2271 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2272 static void VM_SV_getsurfacenormal(void)
2275 msurface_t *surface;
2277 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal);
2278 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2279 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2281 // FIXME: implement rotation/scaling
2282 // note: this (incorrectly) assumes it is a simple polygon
2283 // note: this only returns the first triangle, so it doesn't work very
2284 // well for curved surfaces or arbitrary meshes
2285 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);
2286 VectorNormalize(normal);
2287 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2289 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2290 static void VM_SV_getsurfacetexture(void)
2293 msurface_t *surface;
2294 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture);
2295 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2296 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2298 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2300 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2301 static void VM_SV_getsurfacenearpoint(void)
2303 int surfacenum, best;
2305 vec_t dist, bestdist;
2308 msurface_t *surface;
2310 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint);
2311 PRVM_G_FLOAT(OFS_RETURN) = -1;
2312 ed = PRVM_G_EDICT(OFS_PARM0);
2313 point = PRVM_G_VECTOR(OFS_PARM1);
2315 if (!ed || ed->priv.server->free)
2317 model = getmodel(ed);
2318 if (!model || !model->num_surfaces)
2321 // FIXME: implement rotation/scaling
2322 VectorSubtract(point, ed->fields.server->origin, p);
2324 bestdist = 1000000000;
2325 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2327 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2328 // first see if the nearest point on the surface's box is closer than the previous match
2329 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2330 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2331 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2332 dist = VectorLength2(clipped);
2333 if (dist < bestdist)
2335 // it is, check the nearest point on the actual geometry
2336 clippointtosurface(model, surface, p, clipped);
2337 VectorSubtract(clipped, p, clipped);
2338 dist += VectorLength2(clipped);
2339 if (dist < bestdist)
2341 // that's closer too, store it as the best match
2347 PRVM_G_FLOAT(OFS_RETURN) = best;
2349 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2350 static void VM_SV_getsurfaceclippedpoint(void)
2354 msurface_t *surface;
2356 VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint);
2357 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2358 ed = PRVM_G_EDICT(OFS_PARM0);
2359 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2361 // FIXME: implement rotation/scaling
2362 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2363 clippointtosurface(model, surface, p, out);
2364 // FIXME: implement rotation/scaling
2365 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2368 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2369 //this function originally written by KrimZon, made shorter by LordHavoc
2370 static void VM_SV_clientcommand (void)
2372 client_t *temp_client;
2374 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2376 //find client for this entity
2377 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2378 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2380 Con_Print("PF_clientcommand: entity is not a client\n");
2384 temp_client = host_client;
2385 host_client = svs.clients + i;
2386 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2387 host_client = temp_client;
2390 //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)
2391 static void VM_SV_setattachment (void)
2393 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2394 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2395 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2399 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2401 if (e == prog->edicts)
2403 VM_Warning("setattachment: can not modify world entity\n");
2406 if (e->priv.server->free)
2408 VM_Warning("setattachment: can not modify free entity\n");
2412 if (tagentity == NULL)
2413 tagentity = prog->edicts;
2415 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2417 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2419 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2422 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2424 modelindex = (int)tagentity->fields.server->modelindex;
2425 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2427 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2429 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);
2432 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));
2436 /////////////////////////////////////////
2437 // DP_MD3_TAGINFO extension coded by VorteX
2439 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2444 i = (int)e->fields.server->modelindex;
2445 if (i < 1 || i >= MAX_MODELS)
2447 model = sv.models[i];
2449 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2452 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2454 float scale = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale)->_float;
2458 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);
2460 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);
2463 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2469 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2470 && (model = sv.models[(int)ent->fields.server->modelindex])
2471 && model->animscenes)
2473 // if model has wrong frame, engine automatically switches to model first frame
2474 frame = (int)ent->fields.server->frame;
2475 if (frame < 0 || frame >= model->numframes)
2477 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2479 *out = identitymatrix;
2483 // Warnings/errors code:
2484 // 0 - normal (everything all-right)
2487 // 3 - null or non-precached model
2488 // 4 - no tags with requested index
2489 // 5 - runaway loop at attachment chain
2490 extern cvar_t cl_bob;
2491 extern cvar_t cl_bobcycle;
2492 extern cvar_t cl_bobup;
2493 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2497 int modelindex, attachloop;
2498 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2501 *out = identitymatrix; // warnings and errors return identical matrix
2503 if (ent == prog->edicts)
2505 if (ent->priv.server->free)
2508 modelindex = (int)ent->fields.server->modelindex;
2509 if (modelindex <= 0 || modelindex > MAX_MODELS)
2512 model = sv.models[modelindex];
2514 tagmatrix = identitymatrix;
2515 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2519 if (attachloop >= 256) // prevent runaway looping
2521 // apply transformation by child's tagindex on parent entity and then
2522 // by parent entity itself
2523 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2524 if (ret && attachloop == 0)
2526 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2527 SV_GetEntityMatrix(ent, &entitymatrix, false);
2528 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2529 // next iteration we process the parent entity
2530 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2532 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2533 ent = PRVM_EDICT_NUM(val->edict);
2540 // RENDER_VIEWMODEL magic
2541 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2543 Matrix4x4_Copy(&tagmatrix, out);
2544 ent = PRVM_EDICT_NUM(val->edict);
2546 SV_GetEntityMatrix(ent, &entitymatrix, true);
2547 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2550 // Cl_bob, ported from rendering code
2551 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2554 // LordHavoc: this code is *weird*, but not replacable (I think it
2555 // should be done in QC on the server, but oh well, quake is quake)
2556 // LordHavoc: figured out bobup: the time at which the sin is at 180
2557 // degrees (which allows lengthening or squishing the peak or valley)
2558 cycle = sv.time/cl_bobcycle.value;
2559 cycle -= (int)cycle;
2560 if (cycle < cl_bobup.value)
2561 cycle = sin(M_PI * cycle / cl_bobup.value);
2563 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2564 // bob is proportional to velocity in the xy plane
2565 // (don't count Z, or jumping messes it up)
2566 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;
2567 bob = bob*0.3 + bob*0.7*cycle;
2568 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2575 //float(entity ent, string tagname) gettagindex;
2577 static void VM_SV_gettagindex (void)
2580 const char *tag_name;
2581 int modelindex, tag_index;
2583 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2585 ent = PRVM_G_EDICT(OFS_PARM0);
2586 tag_name = PRVM_G_STRING(OFS_PARM1);
2588 if (ent == prog->edicts)
2590 VM_Warning("gettagindex: can't affect world entity\n");
2593 if (ent->priv.server->free)
2595 VM_Warning("gettagindex: can't affect free entity\n");
2599 modelindex = (int)ent->fields.server->modelindex;
2601 if (modelindex <= 0 || modelindex > MAX_MODELS)
2602 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2605 tag_index = SV_GetTagIndex(ent, tag_name);
2607 if(developer.integer >= 100)
2608 Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2610 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2613 //vector(entity ent, float tagindex) gettaginfo;
2614 static void VM_SV_gettaginfo (void)
2618 matrix4x4_t tag_matrix;
2621 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2623 e = PRVM_G_EDICT(OFS_PARM0);
2624 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2626 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2627 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2632 VM_Warning("gettagindex: can't affect world entity\n");
2635 VM_Warning("gettagindex: can't affect free entity\n");
2638 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2641 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2644 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2649 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2650 static void VM_SV_dropclient (void)
2653 client_t *oldhostclient;
2654 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2655 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2656 if (clientnum < 0 || clientnum >= svs.maxclients)
2658 VM_Warning("dropclient: not a client\n");
2661 if (!svs.clients[clientnum].active)
2663 VM_Warning("dropclient: that client slot is not connected\n");
2666 oldhostclient = host_client;
2667 host_client = svs.clients + clientnum;
2668 SV_DropClient(false);
2669 host_client = oldhostclient;
2672 //entity() spawnclient (DP_SV_BOTCLIENT)
2673 static void VM_SV_spawnclient (void)
2677 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2678 prog->xfunction->builtinsprofile += 2;
2680 for (i = 0;i < svs.maxclients;i++)
2682 if (!svs.clients[i].active)
2684 prog->xfunction->builtinsprofile += 100;
2685 SV_ConnectClient (i, NULL);
2686 // this has to be set or else ClientDisconnect won't be called
2687 // we assume the qc will call ClientConnect...
2688 svs.clients[i].clientconnectcalled = true;
2689 ed = PRVM_EDICT_NUM(i + 1);
2693 VM_RETURN_EDICT(ed);
2696 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2697 static void VM_SV_clienttype (void)
2700 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2701 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2702 if (clientnum < 0 || clientnum >= svs.maxclients)
2703 PRVM_G_FLOAT(OFS_RETURN) = 3;
2704 else if (!svs.clients[clientnum].active)
2705 PRVM_G_FLOAT(OFS_RETURN) = 0;
2706 else if (svs.clients[clientnum].netconnection)
2707 PRVM_G_FLOAT(OFS_RETURN) = 1;
2709 PRVM_G_FLOAT(OFS_RETURN) = 2;
2716 string(string key) serverkey
2719 void VM_SV_serverkey(void)
2721 char string[VM_STRINGTEMP_LENGTH];
2722 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2723 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2724 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2727 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2728 static void VM_SV_setmodelindex (void)
2733 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2735 e = PRVM_G_EDICT(OFS_PARM0);
2736 if (e == prog->edicts)
2738 VM_Warning("setmodelindex: can not modify world entity\n");
2741 if (e->priv.server->free)
2743 VM_Warning("setmodelindex: can not modify free entity\n");
2746 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2747 if (i <= 0 || i > MAX_MODELS)
2749 VM_Warning("setmodelindex: invalid modelindex\n");
2752 if (!sv.model_precache[i][0])
2754 VM_Warning("setmodelindex: model not precached\n");
2758 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2759 e->fields.server->modelindex = i;
2765 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2766 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2768 SetMinMaxSize (e, quakemins, quakemaxs, true);
2771 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2774 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2775 static void VM_SV_modelnameforindex (void)
2778 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2780 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2782 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2783 if (i <= 0 || i > MAX_MODELS)
2785 VM_Warning("modelnameforindex: invalid modelindex\n");
2788 if (!sv.model_precache[i][0])
2790 VM_Warning("modelnameforindex: model not precached\n");
2794 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2797 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2798 static void VM_SV_particleeffectnum (void)
2801 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2802 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2805 PRVM_G_FLOAT(OFS_RETURN) = i;
2808 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2809 static void VM_SV_trailparticles (void)
2811 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2813 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2816 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2817 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2818 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2819 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2820 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2821 SV_FlushBroadcastMessages();
2824 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2825 static void VM_SV_pointparticles (void)
2827 int effectnum, count;
2829 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2831 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2834 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2835 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2836 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2837 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2838 if (count == 1 && !VectorLength2(vel))
2841 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2842 MSG_WriteShort(&sv.datagram, effectnum);
2843 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2847 // 1+2+12+12+2=29 bytes
2848 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2849 MSG_WriteShort(&sv.datagram, effectnum);
2850 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2851 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2852 MSG_WriteShort(&sv.datagram, count);
2855 SV_FlushBroadcastMessages();
2858 prvm_builtin_t vm_sv_builtins[] = {
2859 NULL, // #0 NULL function (not callable) (QUAKE)
2860 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
2861 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
2862 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
2863 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
2864 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
2865 VM_break, // #6 void() break (QUAKE)
2866 VM_random, // #7 float() random (QUAKE)
2867 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
2868 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
2869 VM_error, // #10 void(string e) error (QUAKE)
2870 VM_objerror, // #11 void(string e) objerror (QUAKE)
2871 VM_vlen, // #12 float(vector v) vlen (QUAKE)
2872 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
2873 VM_spawn, // #14 entity() spawn (QUAKE)
2874 VM_remove, // #15 void(entity e) remove (QUAKE)
2875 VM_SV_traceline, // #16 float(vector v1, vector v2, float tryents) traceline (QUAKE)
2876 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
2877 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
2878 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
2879 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
2880 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
2881 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
2882 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
2883 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
2884 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
2885 VM_ftos, // #26 string(float f) ftos (QUAKE)
2886 VM_vtos, // #27 string(vector v) vtos (QUAKE)
2887 VM_coredump, // #28 void() coredump (QUAKE)
2888 VM_traceon, // #29 void() traceon (QUAKE)
2889 VM_traceoff, // #30 void() traceoff (QUAKE)
2890 VM_eprint, // #31 void(entity e) eprint (QUAKE)
2891 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
2892 NULL, // #33 (QUAKE)
2893 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
2894 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
2895 VM_rint, // #36 float(float v) rint (QUAKE)
2896 VM_floor, // #37 float(float v) floor (QUAKE)
2897 VM_ceil, // #38 float(float v) ceil (QUAKE)
2898 NULL, // #39 (QUAKE)
2899 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
2900 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
2901 NULL, // #42 (QUAKE)
2902 VM_fabs, // #43 float(float f) fabs (QUAKE)
2903 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
2904 VM_cvar, // #45 float(string s) cvar (QUAKE)
2905 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
2906 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
2907 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
2908 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
2909 NULL, // #50 (QUAKE)
2910 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
2911 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
2912 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
2913 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
2914 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
2915 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
2916 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
2917 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
2918 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
2919 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
2920 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
2921 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
2922 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
2923 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
2924 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
2925 NULL, // #66 (QUAKE)
2926 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
2927 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
2928 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
2929 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
2930 NULL, // #71 (QUAKE)
2931 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
2932 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
2933 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
2934 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
2935 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
2936 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
2937 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
2938 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
2939 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
2940 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2941 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
2942 NULL, // #83 (QUAKE)
2943 NULL, // #84 (QUAKE)
2944 NULL, // #85 (QUAKE)
2945 NULL, // #86 (QUAKE)
2946 NULL, // #87 (QUAKE)
2947 NULL, // #88 (QUAKE)
2948 NULL, // #89 (QUAKE)
2949 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2950 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2951 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2952 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2953 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2954 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2955 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2956 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2957 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2958 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2959 // FrikaC and Telejano range #100-#199
2970 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2971 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2972 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2973 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2974 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2975 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
2976 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2977 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2978 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2979 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3060 // FTEQW range #200-#299
3079 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3082 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3083 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3084 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3085 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3086 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3087 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3088 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3089 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3090 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3091 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3093 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3161 // CSQC range #300-#399
3162 NULL, // #300 void() clearscene (EXT_CSQC)
3163 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3164 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3165 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3166 NULL, // #304 void() renderscene (EXT_CSQC)
3167 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3168 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3169 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3170 NULL, // #308 void() R_EndPolygon
3172 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3173 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3177 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3178 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3179 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3180 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3181 NULL, // #319 void(string name) freepic (EXT_CSQC)
3182 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3183 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3184 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3185 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3186 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3187 NULL, // #325 void(void) drawresetcliparea
3192 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3193 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3194 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3195 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3196 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3197 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3198 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3199 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3200 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3201 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3202 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3203 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3204 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3205 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3206 NULL, // #344 vector() getmousepos (EXT_CSQC)
3207 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3208 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3209 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3210 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3211 NULL, // #349 float() isdemo (EXT_CSQC)
3212 VM_isserver, // #350 float() isserver (EXT_CSQC)
3213 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3214 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3215 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3216 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3222 NULL, // #360 float() readbyte (EXT_CSQC)
3223 NULL, // #361 float() readchar (EXT_CSQC)
3224 NULL, // #362 float() readshort (EXT_CSQC)
3225 NULL, // #363 float() readlong (EXT_CSQC)
3226 NULL, // #364 float() readcoord (EXT_CSQC)
3227 NULL, // #365 float() readangle (EXT_CSQC)
3228 NULL, // #366 string() readstring (EXT_CSQC)
3229 NULL, // #367 float() readfloat (EXT_CSQC)
3262 // LordHavoc's range #400-#499
3263 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3264 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3265 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3266 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3267 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3268 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3269 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3270 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3271 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)
3272 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3273 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3274 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3275 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3276 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3277 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3278 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3279 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3280 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3281 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3282 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3283 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3284 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3285 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3286 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3287 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3288 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3289 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3290 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3291 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3292 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3293 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3294 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3295 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3296 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3297 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3298 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3299 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3300 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3301 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3302 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3303 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3304 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3305 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3306 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3307 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3308 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3309 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3310 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3311 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3312 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3313 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3314 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3315 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3316 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3317 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3318 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3319 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3320 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3322 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3323 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3324 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3325 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3326 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3327 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3328 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3329 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3330 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3331 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3332 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3334 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3335 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3336 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3337 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3338 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3339 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3340 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3341 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3342 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3343 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3344 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3345 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3346 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3347 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3348 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3349 VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3357 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3358 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3373 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3374 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3375 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3385 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3387 void VM_SV_Cmd_Init(void)
3392 void VM_SV_Cmd_Reset(void)
3394 if(prog->funcoffsets.SV_Shutdown)
3396 func_t s = prog->funcoffsets.SV_Shutdown;
3397 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3398 PRVM_ExecuteProgram(s,"SV_Shutdown() required");