6 //============================================================================
11 char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
35 "DP_ENT_CUSTOMCOLORMAP "
36 "DP_ENT_EXTERIORMODELTOCLIENT "
38 "DP_ENT_LOWPRECISION "
42 "DP_GFX_EXTERNALTEXTURES "
43 "DP_GFX_EXTERNALTEXTURES_PERMAP "
45 "DP_GFX_QUAKE3MODELTAGS "
49 "DP_HALFLIFE_MAP_CVAR "
55 "DP_MOVETYPEBOUNCEMISSILE "
57 "DP_QC_ASINACOSATANATAN2TAN "
62 "DP_QC_CVAR_DEFSTRING "
69 "DP_QC_FINDCHAINFLAGS "
70 "DP_QC_FINDCHAINFLOAT "
76 "DP_QC_GETSURFACEPOINTATTRIBUTE "
79 "DP_QC_MULTIPLETEMPSTRINGS "
80 "DP_QC_NUM_FOR_EDICT "
82 "DP_QC_SINCOSSQRTPOW "
84 "DP_QC_STRINGBUFFERS "
85 "DP_QC_STRINGCOLORFUNCTIONS "
86 "DP_QC_STRING_CASE_FUNCTIONS "
88 "DP_QC_TOKENIZEBYSEPARATOR "
91 "DP_QC_TRACE_MOVETYPE_HITMODEL "
92 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
93 "DP_QC_UNLIMITEDTEMPSTRINGS "
96 "DP_QC_VECTOANGLES_WITH_ROLL "
97 "DP_QC_VECTORVECTORS "
104 "DP_SND_DIRECTIONLESSATTNNONE "
111 "DP_SV_CLIENTCOLORS "
114 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
115 "DP_SV_DRAWONLYTOCLIENT "
118 "DP_SV_ENTITYCONTENTSTRANSITION "
119 "DP_SV_MODELFLAGS_AS_EFFECTS "
120 "DP_SV_MOVETYPESTEP_LANDEVENT "
122 "DP_SV_NODRAWTOCLIENT "
123 "DP_SV_ONENTITYNOSPAWNFUNCTION "
125 "DP_SV_PLAYERPHYSICS "
126 "DP_SV_POINTPARTICLES "
128 "DP_SV_PRECACHEANYTIME "
132 "DP_SV_ROTATINGBMODEL "
136 "DP_SV_SPAWNFUNC_PREFIX "
137 "DP_SV_WRITEPICTURE "
138 "DP_SV_WRITEUNTERMINATEDSTRING "
142 "DP_TE_EXPLOSIONRGB "
144 "DP_TE_PARTICLECUBE "
145 "DP_TE_PARTICLERAIN "
146 "DP_TE_PARTICLESNOW "
148 "DP_TE_QUADEFFECTS1 "
151 "DP_TE_STANDARDEFFECTBUILTINS "
152 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
157 "KRIMZON_SV_PARSECLIENTCOMMAND "
160 "NEXUIZ_PLAYERMODEL "
162 "PRYDON_CLIENTCURSOR "
163 "TENEBRAE_GFX_DLIGHTS "
165 //"EXT_CSQC " // not ready yet
172 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.
174 setorigin (entity, origin)
177 static void VM_SV_setorigin (void)
182 VM_SAFEPARMCOUNT(2, VM_setorigin);
184 e = PRVM_G_EDICT(OFS_PARM0);
185 if (e == prog->edicts)
187 VM_Warning("setorigin: can not modify world entity\n");
190 if (e->priv.server->free)
192 VM_Warning("setorigin: can not modify free entity\n");
195 org = PRVM_G_VECTOR(OFS_PARM1);
196 VectorCopy (org, e->fields.server->origin);
197 SV_LinkEdict (e, false);
200 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
201 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
205 for (i=0 ; i<3 ; i++)
207 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
209 // set derived values
210 VectorCopy (min, e->fields.server->mins);
211 VectorCopy (max, e->fields.server->maxs);
212 VectorSubtract (max, min, e->fields.server->size);
214 SV_LinkEdict (e, false);
221 the size box is rotated by the current angle
222 LordHavoc: no it isn't...
224 setsize (entity, minvector, maxvector)
227 static void VM_SV_setsize (void)
232 VM_SAFEPARMCOUNT(3, VM_setsize);
234 e = PRVM_G_EDICT(OFS_PARM0);
235 if (e == prog->edicts)
237 VM_Warning("setsize: can not modify world entity\n");
240 if (e->priv.server->free)
242 VM_Warning("setsize: can not modify free entity\n");
245 min = PRVM_G_VECTOR(OFS_PARM1);
246 max = PRVM_G_VECTOR(OFS_PARM2);
247 SetMinMaxSize (e, min, max, false);
255 setmodel(entity, model)
258 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
259 static void VM_SV_setmodel (void)
265 VM_SAFEPARMCOUNT(2, VM_setmodel);
267 e = PRVM_G_EDICT(OFS_PARM0);
268 if (e == prog->edicts)
270 VM_Warning("setmodel: can not modify world entity\n");
273 if (e->priv.server->free)
275 VM_Warning("setmodel: can not modify free entity\n");
278 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
279 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
280 e->fields.server->modelindex = i;
286 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
287 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
289 SetMinMaxSize (e, quakemins, quakemaxs, true);
292 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
299 single print to a specific client
301 sprint(clientent, value)
304 static void VM_SV_sprint (void)
308 char string[VM_STRINGTEMP_LENGTH];
310 VM_VarString(1, string, sizeof(string));
312 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
314 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
315 // LordHavoc: div0 requested that sprintto world operate like print
322 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
324 VM_Warning("tried to centerprint to a non-client\n");
328 client = svs.clients + entnum-1;
329 if (!client->netconnection)
332 MSG_WriteChar(&client->netconnection->message,svc_print);
333 MSG_WriteString(&client->netconnection->message, string);
341 single print to a specific client
343 centerprint(clientent, value)
346 static void VM_SV_centerprint (void)
350 char string[VM_STRINGTEMP_LENGTH];
352 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
354 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
356 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
358 VM_Warning("tried to centerprint to a non-client\n");
362 client = svs.clients + entnum-1;
363 if (!client->netconnection)
366 VM_VarString(1, string, sizeof(string));
367 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
368 MSG_WriteString(&client->netconnection->message, string);
375 particle(origin, color, count)
378 static void VM_SV_particle (void)
384 VM_SAFEPARMCOUNT(4, VM_SV_particle);
386 org = PRVM_G_VECTOR(OFS_PARM0);
387 dir = PRVM_G_VECTOR(OFS_PARM1);
388 color = PRVM_G_FLOAT(OFS_PARM2);
389 count = PRVM_G_FLOAT(OFS_PARM3);
390 SV_StartParticle (org, dir, (int)color, (int)count);
400 static void VM_SV_ambientsound (void)
404 float vol, attenuation;
407 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
409 pos = PRVM_G_VECTOR (OFS_PARM0);
410 samp = PRVM_G_STRING(OFS_PARM1);
411 vol = PRVM_G_FLOAT(OFS_PARM2);
412 attenuation = PRVM_G_FLOAT(OFS_PARM3);
414 // check to see if samp was properly precached
415 soundnum = SV_SoundIndex(samp, 1);
423 // add an svc_spawnambient command to the level signon packet
426 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
428 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
430 MSG_WriteVector(&sv.signon, pos, sv.protocol);
432 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
433 MSG_WriteShort (&sv.signon, soundnum);
435 MSG_WriteByte (&sv.signon, soundnum);
437 MSG_WriteByte (&sv.signon, (int)(vol*255));
438 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
446 Each entity can have eight independant sound sources, like voice,
449 Channel 0 is an auto-allocate channel, the others override anything
450 already running on that entity/channel pair.
452 An attenuation of 0 will play full volume everywhere in the level.
453 Larger attenuations will drop off.
457 static void VM_SV_sound (void)
461 prvm_edict_t *entity;
465 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
467 entity = PRVM_G_EDICT(OFS_PARM0);
468 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
469 sample = PRVM_G_STRING(OFS_PARM2);
470 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
471 attenuation = PRVM_G_FLOAT(OFS_PARM4);
474 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
478 if (volume < 0 || volume > 255)
480 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
484 if (attenuation < 0 || attenuation > 4)
486 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
490 if (channel < 0 || channel > 7)
492 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
496 SV_StartSound (entity, channel, sample, volume, attenuation);
503 Follows the same logic as VM_SV_sound, except instead of
504 an entity, an origin for the sound is provided, and channel
505 is omitted (since no entity is being tracked).
509 static void VM_SV_pointsound(void)
516 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
518 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
519 sample = PRVM_G_STRING(OFS_PARM1);
520 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
521 attenuation = PRVM_G_FLOAT(OFS_PARM3);
523 if (volume < 0 || volume > 255)
525 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
529 if (attenuation < 0 || attenuation > 4)
531 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
535 SV_StartPointSound (org, sample, volume, attenuation);
542 Used for use tracing and shot targeting
543 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
544 if the tryents flag is set.
546 traceline (vector1, vector2, movetype, ignore)
549 static void VM_SV_traceline (void)
556 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
558 prog->xfunction->builtinsprofile += 30;
560 v1 = PRVM_G_VECTOR(OFS_PARM0);
561 v2 = PRVM_G_VECTOR(OFS_PARM1);
562 move = (int)PRVM_G_FLOAT(OFS_PARM2);
563 ent = PRVM_G_EDICT(OFS_PARM3);
565 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]))
566 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));
568 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
570 VM_SetTraceGlobals(&trace);
578 Used for use tracing and shot targeting
579 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
580 if the tryents flag is set.
582 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
585 // LordHavoc: added this for my own use, VERY useful, similar to traceline
586 static void VM_SV_tracebox (void)
588 float *v1, *v2, *m1, *m2;
593 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
595 prog->xfunction->builtinsprofile += 30;
597 v1 = PRVM_G_VECTOR(OFS_PARM0);
598 m1 = PRVM_G_VECTOR(OFS_PARM1);
599 m2 = PRVM_G_VECTOR(OFS_PARM2);
600 v2 = PRVM_G_VECTOR(OFS_PARM3);
601 move = (int)PRVM_G_FLOAT(OFS_PARM4);
602 ent = PRVM_G_EDICT(OFS_PARM5);
604 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]))
605 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));
607 trace = SV_Move (v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
609 VM_SetTraceGlobals(&trace);
612 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
617 vec3_t original_origin;
618 vec3_t original_velocity;
619 vec3_t original_angles;
620 vec3_t original_avelocity;
624 VectorCopy(tossent->fields.server->origin , original_origin );
625 VectorCopy(tossent->fields.server->velocity , original_velocity );
626 VectorCopy(tossent->fields.server->angles , original_angles );
627 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
629 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
630 if (val != NULL && val->_float != 0)
631 gravity = val->_float;
634 gravity *= sv_gravity.value * 0.05;
636 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
638 SV_CheckVelocity (tossent);
639 tossent->fields.server->velocity[2] -= gravity;
640 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
641 VectorScale (tossent->fields.server->velocity, 0.05, move);
642 VectorAdd (tossent->fields.server->origin, move, end);
643 trace = SV_Move (tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
644 VectorCopy (trace.endpos, tossent->fields.server->origin);
646 if (trace.fraction < 1)
650 VectorCopy(original_origin , tossent->fields.server->origin );
651 VectorCopy(original_velocity , tossent->fields.server->velocity );
652 VectorCopy(original_angles , tossent->fields.server->angles );
653 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
658 static void VM_SV_tracetoss (void)
662 prvm_edict_t *ignore;
664 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
666 prog->xfunction->builtinsprofile += 600;
668 ent = PRVM_G_EDICT(OFS_PARM0);
669 if (ent == prog->edicts)
671 VM_Warning("tracetoss: can not use world entity\n");
674 ignore = PRVM_G_EDICT(OFS_PARM1);
676 trace = SV_Trace_Toss (ent, ignore);
678 VM_SetTraceGlobals(&trace);
681 //============================================================================
683 static int checkpvsbytes;
684 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
686 static int VM_SV_newcheckclient (int check)
692 // cycle to the next one
694 check = bound(1, check, svs.maxclients);
695 if (check == svs.maxclients)
703 prog->xfunction->builtinsprofile++;
705 if (i == svs.maxclients+1)
707 // look up the client's edict
708 ent = PRVM_EDICT_NUM(i);
709 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
710 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
712 // found a valid client (possibly the same one again)
716 // get the PVS for the entity
717 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
719 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
720 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
729 Returns a client (or object that has a client enemy) that would be a
732 If there is more than one valid option, they are cycled each frame
734 If (self.origin + self.viewofs) is not in the PVS of the current target,
735 it is not returned at all.
740 int c_invis, c_notvis;
741 static void VM_SV_checkclient (void)
743 prvm_edict_t *ent, *self;
746 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
748 // find a new check if on a new frame
749 if (sv.time - sv.lastchecktime >= 0.1)
751 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
752 sv.lastchecktime = sv.time;
755 // return check if it might be visible
756 ent = PRVM_EDICT_NUM(sv.lastcheck);
757 if (ent->priv.server->free || ent->fields.server->health <= 0)
759 VM_RETURN_EDICT(prog->edicts);
763 // if current entity can't possibly see the check entity, return 0
764 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
765 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
766 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
769 VM_RETURN_EDICT(prog->edicts);
773 // might be able to see it
775 VM_RETURN_EDICT(ent);
778 //============================================================================
785 Sends text over to the client's execution buffer
787 stuffcmd (clientent, value, ...)
790 static void VM_SV_stuffcmd (void)
794 char string[VM_STRINGTEMP_LENGTH];
796 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
798 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
799 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
801 VM_Warning("Can't stuffcmd to a non-client\n");
805 VM_VarString(1, string, sizeof(string));
808 host_client = svs.clients + entnum-1;
809 Host_ClientCommands ("%s", string);
817 Returns a chain of entities that have origins within a spherical area
819 findradius (origin, radius)
822 static void VM_SV_findradius (void)
824 prvm_edict_t *ent, *chain;
825 vec_t radius, radius2;
826 vec3_t org, eorg, mins, maxs;
829 prvm_edict_t *touchedicts[MAX_EDICTS];
831 VM_SAFEPARMCOUNT(2, VM_SV_findradius);
833 chain = (prvm_edict_t *)prog->edicts;
835 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
836 radius = PRVM_G_FLOAT(OFS_PARM1);
837 radius2 = radius * radius;
839 mins[0] = org[0] - (radius + 1);
840 mins[1] = org[1] - (radius + 1);
841 mins[2] = org[2] - (radius + 1);
842 maxs[0] = org[0] + (radius + 1);
843 maxs[1] = org[1] + (radius + 1);
844 maxs[2] = org[2] + (radius + 1);
845 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
846 if (numtouchedicts > MAX_EDICTS)
848 // this never happens
849 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
850 numtouchedicts = MAX_EDICTS;
852 for (i = 0;i < numtouchedicts;i++)
854 ent = touchedicts[i];
855 prog->xfunction->builtinsprofile++;
856 // Quake did not return non-solid entities but darkplaces does
857 // (note: this is the reason you can't blow up fallen zombies)
858 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
860 // LordHavoc: compare against bounding box rather than center so it
861 // doesn't miss large objects, and use DotProduct instead of Length
862 // for a major speedup
863 VectorSubtract(org, ent->fields.server->origin, eorg);
864 if (sv_gameplayfix_findradiusdistancetobox.integer)
866 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
867 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
868 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
871 VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
872 if (DotProduct(eorg, eorg) < radius2)
874 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
879 VM_RETURN_EDICT(chain);
882 static void VM_SV_precache_sound (void)
884 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
885 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
888 static void VM_SV_precache_model (void)
890 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
891 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
892 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
899 float(float yaw, float dist[, settrace]) walkmove
902 static void VM_SV_walkmove (void)
911 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
913 // assume failure if it returns early
914 PRVM_G_FLOAT(OFS_RETURN) = 0;
916 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
917 if (ent == prog->edicts)
919 VM_Warning("walkmove: can not modify world entity\n");
922 if (ent->priv.server->free)
924 VM_Warning("walkmove: can not modify free entity\n");
927 yaw = PRVM_G_FLOAT(OFS_PARM0);
928 dist = PRVM_G_FLOAT(OFS_PARM1);
929 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
931 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
934 yaw = yaw*M_PI*2 / 360;
936 move[0] = cos(yaw)*dist;
937 move[1] = sin(yaw)*dist;
940 // save program state, because SV_movestep may call other progs
941 oldf = prog->xfunction;
942 oldself = prog->globals.server->self;
944 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
947 // restore program state
948 prog->xfunction = oldf;
949 prog->globals.server->self = oldself;
959 static void VM_SV_droptofloor (void)
965 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
967 // assume failure if it returns early
968 PRVM_G_FLOAT(OFS_RETURN) = 0;
970 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
971 if (ent == prog->edicts)
973 VM_Warning("droptofloor: can not modify world entity\n");
976 if (ent->priv.server->free)
978 VM_Warning("droptofloor: can not modify free entity\n");
982 VectorCopy (ent->fields.server->origin, end);
985 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
986 SV_UnstickEntity(ent);
988 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
989 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
992 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]);
993 VectorAdd(ent->fields.server->origin, offset, org);
994 trace = SV_Move (org, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
995 VectorSubtract(trace.endpos, offset, trace.endpos);
996 if (trace.startsolid)
998 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]);
999 SV_UnstickEntity(ent);
1000 SV_LinkEdict (ent, false);
1001 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1002 ent->fields.server->groundentity = 0;
1003 PRVM_G_FLOAT(OFS_RETURN) = 1;
1005 else if (trace.fraction < 1)
1007 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]);
1008 VectorCopy (trace.endpos, ent->fields.server->origin);
1009 SV_UnstickEntity(ent);
1010 SV_LinkEdict (ent, false);
1011 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1012 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1013 PRVM_G_FLOAT(OFS_RETURN) = 1;
1014 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1015 ent->priv.server->suspendedinairflag = true;
1020 if (trace.fraction != 1)
1022 if (trace.fraction < 1)
1023 VectorCopy (trace.endpos, ent->fields.server->origin);
1024 SV_LinkEdict (ent, false);
1025 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1026 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1027 PRVM_G_FLOAT(OFS_RETURN) = 1;
1028 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1029 ent->priv.server->suspendedinairflag = true;
1038 void(float style, string value) lightstyle
1041 static void VM_SV_lightstyle (void)
1048 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1050 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1051 val = PRVM_G_STRING(OFS_PARM1);
1053 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1054 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1057 // change the string in sv
1058 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1060 // send message to all clients on this server
1061 if (sv.state != ss_active)
1064 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1066 if (client->active && client->netconnection)
1068 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1069 MSG_WriteChar (&client->netconnection->message,style);
1070 MSG_WriteString (&client->netconnection->message, val);
1080 static void VM_SV_checkbottom (void)
1082 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1083 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1091 static void VM_SV_pointcontents (void)
1093 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1094 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1101 Pick a vector for the player to shoot along
1102 vector aim(entity, missilespeed)
1105 static void VM_SV_aim (void)
1107 prvm_edict_t *ent, *check, *bestent;
1108 vec3_t start, dir, end, bestdir;
1111 float dist, bestdist;
1114 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1116 // assume failure if it returns early
1117 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1118 // if sv_aim is so high it can't possibly accept anything, skip out early
1119 if (sv_aim.value >= 1)
1122 ent = PRVM_G_EDICT(OFS_PARM0);
1123 if (ent == prog->edicts)
1125 VM_Warning("aim: can not use world entity\n");
1128 if (ent->priv.server->free)
1130 VM_Warning("aim: can not use free entity\n");
1133 speed = PRVM_G_FLOAT(OFS_PARM1);
1135 VectorCopy (ent->fields.server->origin, start);
1138 // try sending a trace straight
1139 VectorCopy (prog->globals.server->v_forward, dir);
1140 VectorMA (start, 2048, dir, end);
1141 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1142 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1143 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1145 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1150 // try all possible entities
1151 VectorCopy (dir, bestdir);
1152 bestdist = sv_aim.value;
1155 check = PRVM_NEXT_EDICT(prog->edicts);
1156 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1158 prog->xfunction->builtinsprofile++;
1159 if (check->fields.server->takedamage != DAMAGE_AIM)
1163 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1164 continue; // don't aim at teammate
1165 for (j=0 ; j<3 ; j++)
1166 end[j] = check->fields.server->origin[j]
1167 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1168 VectorSubtract (end, start, dir);
1169 VectorNormalize (dir);
1170 dist = DotProduct (dir, prog->globals.server->v_forward);
1171 if (dist < bestdist)
1172 continue; // to far to turn
1173 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1174 if (tr.ent == check)
1175 { // can shoot at this one
1183 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1184 dist = DotProduct (dir, prog->globals.server->v_forward);
1185 VectorScale (prog->globals.server->v_forward, dist, end);
1187 VectorNormalize (end);
1188 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1192 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1197 ===============================================================================
1201 ===============================================================================
1204 #define MSG_BROADCAST 0 // unreliable to all
1205 #define MSG_ONE 1 // reliable to one (msg_entity)
1206 #define MSG_ALL 2 // reliable to all
1207 #define MSG_INIT 3 // write to the init string
1208 #define MSG_ENTITY 5
1210 sizebuf_t *WriteDest (void)
1216 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1220 return &sv.datagram;
1223 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1224 entnum = PRVM_NUM_FOR_EDICT(ent);
1225 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1227 VM_Warning ("WriteDest: tried to write to non-client\n");
1228 return &sv.reliable_datagram;
1231 return &svs.clients[entnum-1].netconnection->message;
1234 VM_Warning ("WriteDest: bad destination\n");
1236 return &sv.reliable_datagram;
1242 return sv.writeentitiestoclient_msg;
1248 static void VM_SV_WriteByte (void)
1250 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1251 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1254 static void VM_SV_WriteChar (void)
1256 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1257 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1260 static void VM_SV_WriteShort (void)
1262 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1263 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1266 static void VM_SV_WriteLong (void)
1268 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1269 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1272 static void VM_SV_WriteAngle (void)
1274 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1275 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1278 static void VM_SV_WriteCoord (void)
1280 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1281 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1284 static void VM_SV_WriteString (void)
1286 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1287 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1290 static void VM_SV_WriteUnterminatedString (void)
1292 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1293 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1297 static void VM_SV_WriteEntity (void)
1299 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1300 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1303 // writes a picture as at most size bytes of data
1305 // IMGNAME \0 SIZE(short) IMGDATA
1306 // if failed to read/compress:
1308 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1309 static void VM_SV_WritePicture (void)
1311 const char *imgname;
1315 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1317 imgname = PRVM_G_STRING(OFS_PARM1);
1318 size = PRVM_G_FLOAT(OFS_PARM2);
1322 MSG_WriteString(WriteDest(), imgname);
1323 if(Image_Compress(imgname, size, &buf, &size))
1326 MSG_WriteShort(WriteDest(), size);
1327 SZ_Write(WriteDest(), buf, size);
1332 MSG_WriteShort(WriteDest(), 0);
1336 //////////////////////////////////////////////////////////
1338 static void VM_SV_makestatic (void)
1343 // allow 0 parameters due to an id1 qc bug in which this function is used
1344 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1345 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1347 if (prog->argc >= 1)
1348 ent = PRVM_G_EDICT(OFS_PARM0);
1350 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1351 if (ent == prog->edicts)
1353 VM_Warning("makestatic: can not modify world entity\n");
1356 if (ent->priv.server->free)
1358 VM_Warning("makestatic: can not modify free entity\n");
1363 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1368 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1369 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1370 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1372 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1374 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1375 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1376 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1380 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1381 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1382 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1385 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1386 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1387 for (i=0 ; i<3 ; i++)
1389 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1390 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1393 // throw the entity away now
1397 //=============================================================================
1404 static void VM_SV_setspawnparms (void)
1410 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1412 ent = PRVM_G_EDICT(OFS_PARM0);
1413 i = PRVM_NUM_FOR_EDICT(ent);
1414 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1416 Con_Print("tried to setspawnparms on a non-client\n");
1420 // copy spawn parms out of the client_t
1421 client = svs.clients + i-1;
1422 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1423 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1430 Returns a color vector indicating the lighting at the requested point.
1432 (Internal Operation note: actually measures the light beneath the point, just like
1433 the model lighting on the client)
1438 static void VM_SV_getlight (void)
1440 vec3_t ambientcolor, diffusecolor, diffusenormal;
1442 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1443 p = PRVM_G_VECTOR(OFS_PARM0);
1444 VectorClear(ambientcolor);
1445 VectorClear(diffusecolor);
1446 VectorClear(diffusenormal);
1447 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1448 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1449 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1454 unsigned char type; // 1/2/8 or other value if isn't used
1458 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1459 static int vm_customstats_last;
1461 void VM_CustomStats_Clear (void)
1465 Z_Free(vm_customstats);
1466 vm_customstats = NULL;
1467 vm_customstats_last = -1;
1471 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1479 for(i=0; i<vm_customstats_last+1 ;i++)
1481 if(!vm_customstats[i].type)
1483 switch(vm_customstats[i].type)
1485 //string as 16 bytes
1488 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1489 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1490 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1491 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1492 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1494 //float field sent as-is
1496 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1498 //integer value of float field
1500 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1508 // void(float index, float type, .void field) SV_AddStat = #232;
1509 // Set up an auto-sent player stat.
1510 // Client's get thier own fields sent to them. Index may not be less than 32.
1511 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1512 // 1: string (4 stats carrying a total of 16 charactures)
1513 // 2: float (one stat, float converted to an integer for transportation)
1514 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1515 static void VM_SV_AddStat (void)
1520 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1524 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1527 VM_Warning("PF_SV_AddStat: not enough memory\n");
1531 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1532 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1533 off = PRVM_G_INT (OFS_PARM2);
1538 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1541 if(i >= (MAX_CL_STATS-32))
1543 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1546 if(i > (MAX_CL_STATS-32-4) && type == 1)
1548 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1551 vm_customstats[i].type = type;
1552 vm_customstats[i].fieldoffset = off;
1553 if(vm_customstats_last < i)
1554 vm_customstats_last = i;
1561 copies data from one entity to another
1563 copyentity(src, dst)
1566 static void VM_SV_copyentity (void)
1568 prvm_edict_t *in, *out;
1569 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1570 in = PRVM_G_EDICT(OFS_PARM0);
1571 if (in == prog->edicts)
1573 VM_Warning("copyentity: can not read world entity\n");
1576 if (in->priv.server->free)
1578 VM_Warning("copyentity: can not read free entity\n");
1581 out = PRVM_G_EDICT(OFS_PARM1);
1582 if (out == prog->edicts)
1584 VM_Warning("copyentity: can not modify world entity\n");
1587 if (out->priv.server->free)
1589 VM_Warning("copyentity: can not modify free entity\n");
1592 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1593 SV_LinkEdict(out, false);
1601 sets the color of a client and broadcasts the update to all connected clients
1603 setcolor(clientent, value)
1606 static void VM_SV_setcolor (void)
1612 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1613 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1614 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1616 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1618 Con_Print("tried to setcolor a non-client\n");
1622 client = svs.clients + entnum-1;
1625 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1627 client->edict->fields.server->team = (i & 15) + 1;
1630 if (client->old_colors != client->colors)
1632 client->old_colors = client->colors;
1633 // send notification to all clients
1634 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1635 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1636 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1644 effect(origin, modelname, startframe, framecount, framerate)
1647 static void VM_SV_effect (void)
1651 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1652 s = PRVM_G_STRING(OFS_PARM1);
1655 VM_Warning("effect: no model specified\n");
1659 i = SV_ModelIndex(s, 1);
1662 VM_Warning("effect: model not precached\n");
1666 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1668 VM_Warning("effect: framecount < 1\n");
1672 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1674 VM_Warning("effect: framerate < 1\n");
1678 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));
1681 static void VM_SV_te_blood (void)
1683 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1684 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1686 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1687 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1689 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1690 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1691 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1693 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1694 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1695 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1697 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1698 SV_FlushBroadcastMessages();
1701 static void VM_SV_te_bloodshower (void)
1703 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1704 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1706 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1707 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1709 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1710 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1711 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1713 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1714 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1715 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1717 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1719 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1720 SV_FlushBroadcastMessages();
1723 static void VM_SV_te_explosionrgb (void)
1725 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1726 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1727 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1729 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1730 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1731 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1733 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1734 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1735 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1736 SV_FlushBroadcastMessages();
1739 static void VM_SV_te_particlecube (void)
1741 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1742 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1744 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1745 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1747 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1748 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1749 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1751 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1752 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1753 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1755 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1756 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1757 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1759 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1761 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1762 // gravity true/false
1763 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1765 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1766 SV_FlushBroadcastMessages();
1769 static void VM_SV_te_particlerain (void)
1771 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1772 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1774 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1775 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1777 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1778 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1779 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1781 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1782 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1783 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1785 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1786 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1787 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1789 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1791 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1792 SV_FlushBroadcastMessages();
1795 static void VM_SV_te_particlesnow (void)
1797 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1798 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1800 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1801 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1803 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1804 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1805 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1808 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1809 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1812 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1813 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1815 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1817 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1818 SV_FlushBroadcastMessages();
1821 static void VM_SV_te_spark (void)
1823 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1824 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1826 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1827 MSG_WriteByte(&sv.datagram, TE_SPARK);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1830 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1831 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1833 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1834 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1835 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1837 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1838 SV_FlushBroadcastMessages();
1841 static void VM_SV_te_gunshotquad (void)
1843 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1844 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1845 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1847 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1848 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1849 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1850 SV_FlushBroadcastMessages();
1853 static void VM_SV_te_spikequad (void)
1855 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1856 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1857 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1859 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1860 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1861 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1862 SV_FlushBroadcastMessages();
1865 static void VM_SV_te_superspikequad (void)
1867 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1868 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1869 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1873 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1874 SV_FlushBroadcastMessages();
1877 static void VM_SV_te_explosionquad (void)
1879 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
1880 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1881 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1883 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1884 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1885 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1886 SV_FlushBroadcastMessages();
1889 static void VM_SV_te_smallflash (void)
1891 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
1892 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1893 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1895 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1896 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1898 SV_FlushBroadcastMessages();
1901 static void VM_SV_te_customflash (void)
1903 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
1904 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1906 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1907 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1911 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1913 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1915 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1917 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1918 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1919 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1920 SV_FlushBroadcastMessages();
1923 static void VM_SV_te_gunshot (void)
1925 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
1926 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1927 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1932 SV_FlushBroadcastMessages();
1935 static void VM_SV_te_spike (void)
1937 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
1938 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1939 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1941 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1942 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1943 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1944 SV_FlushBroadcastMessages();
1947 static void VM_SV_te_superspike (void)
1949 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
1950 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1951 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1953 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1954 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1955 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1956 SV_FlushBroadcastMessages();
1959 static void VM_SV_te_explosion (void)
1961 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
1962 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1963 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1965 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1968 SV_FlushBroadcastMessages();
1971 static void VM_SV_te_tarexplosion (void)
1973 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
1974 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1975 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1977 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1978 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1979 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1980 SV_FlushBroadcastMessages();
1983 static void VM_SV_te_wizspike (void)
1985 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
1986 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1987 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1989 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1990 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1991 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1992 SV_FlushBroadcastMessages();
1995 static void VM_SV_te_knightspike (void)
1997 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
1998 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1999 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2001 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2002 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2004 SV_FlushBroadcastMessages();
2007 static void VM_SV_te_lavasplash (void)
2009 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2010 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2011 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2014 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2015 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2016 SV_FlushBroadcastMessages();
2019 static void VM_SV_te_teleport (void)
2021 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2022 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2023 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2025 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2026 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2028 SV_FlushBroadcastMessages();
2031 static void VM_SV_te_explosion2 (void)
2033 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2034 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2035 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2037 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2038 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2039 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2041 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2042 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2043 SV_FlushBroadcastMessages();
2046 static void VM_SV_te_lightning1 (void)
2048 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2049 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2050 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2052 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2054 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2055 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2056 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2058 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2059 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2060 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2061 SV_FlushBroadcastMessages();
2064 static void VM_SV_te_lightning2 (void)
2066 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2067 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2068 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2070 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2072 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2074 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2076 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2077 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2078 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2079 SV_FlushBroadcastMessages();
2082 static void VM_SV_te_lightning3 (void)
2084 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2085 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2086 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2088 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2090 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2091 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2092 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2094 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2095 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2096 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2097 SV_FlushBroadcastMessages();
2100 static void VM_SV_te_beam (void)
2102 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2103 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2104 MSG_WriteByte(&sv.datagram, TE_BEAM);
2106 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2108 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2109 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2110 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2112 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2113 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2114 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2115 SV_FlushBroadcastMessages();
2118 static void VM_SV_te_plasmaburn (void)
2120 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2121 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2122 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2123 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2124 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2125 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2126 SV_FlushBroadcastMessages();
2129 static void VM_SV_te_flamejet (void)
2131 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2132 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2133 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2135 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2136 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2137 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2139 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2140 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2141 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2143 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2144 SV_FlushBroadcastMessages();
2147 void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2150 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2152 bestdist = 1000000000;
2154 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2156 // clip original point to each triangle of the surface and find the
2157 // triangle that is closest
2158 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2159 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2160 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2161 TriangleNormal(v[0], v[1], v[2], facenormal);
2162 VectorNormalize(facenormal);
2163 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2164 VectorMA(p, offsetdist, facenormal, temp);
2165 for (j = 0, k = 2;j < 3;k = j, j++)
2167 VectorSubtract(v[k], v[j], edgenormal);
2168 CrossProduct(edgenormal, facenormal, sidenormal);
2169 VectorNormalize(sidenormal);
2170 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2172 VectorMA(temp, offsetdist, sidenormal, temp);
2174 dist = VectorDistance2(temp, p);
2175 if (bestdist > dist)
2178 VectorCopy(temp, out);
2183 static dp_model_t *getmodel(prvm_edict_t *ed)
2186 if (!ed || ed->priv.server->free)
2188 modelindex = (int)ed->fields.server->modelindex;
2189 if (modelindex < 1 || modelindex >= MAX_MODELS)
2191 return sv.models[modelindex];
2194 static msurface_t *getsurface(dp_model_t *model, int surfacenum)
2196 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2198 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2202 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2203 static void VM_SV_getsurfacenumpoints(void)
2206 msurface_t *surface;
2207 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints);
2208 // return 0 if no such surface
2209 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2211 PRVM_G_FLOAT(OFS_RETURN) = 0;
2215 // note: this (incorrectly) assumes it is a simple polygon
2216 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2218 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2219 static void VM_SV_getsurfacepoint(void)
2223 msurface_t *surface;
2225 VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint);
2226 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2227 ed = PRVM_G_EDICT(OFS_PARM0);
2228 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2230 // note: this (incorrectly) assumes it is a simple polygon
2231 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2232 if (pointnum < 0 || pointnum >= surface->num_vertices)
2234 // FIXME: implement rotation/scaling
2235 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2237 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
2238 // float SPA_POSITION = 0;
2239 // float SPA_S_AXIS = 1;
2240 // float SPA_T_AXIS = 2;
2241 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2242 // float SPA_TEXCOORDS0 = 4;
2243 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2244 // float SPA_LIGHTMAP0_COLOR = 6;
2245 static void VM_SV_getsurfacepointattribute(void)
2249 msurface_t *surface;
2253 VM_SAFEPARMCOUNT(4, VM_SV_getsurfacepoint);
2254 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2255 ed = PRVM_G_EDICT(OFS_PARM0);
2256 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2258 // note: this (incorrectly) assumes it is a simple polygon
2259 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2260 if (pointnum < 0 || pointnum >= surface->num_vertices)
2262 // FIXME: implement rotation/scaling
2263 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
2265 switch( attributetype ) {
2266 // float SPA_POSITION = 0;
2268 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2270 // float SPA_S_AXIS = 1;
2272 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2274 // float SPA_T_AXIS = 2;
2276 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2278 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2280 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2282 // float SPA_TEXCOORDS0 = 4;
2284 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2285 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
2286 ret[0] = texcoord[0];
2287 ret[1] = texcoord[1];
2291 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2293 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2294 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
2295 ret[0] = texcoord[0];
2296 ret[1] = texcoord[1];
2300 // float SPA_LIGHTMAP0_COLOR = 6;
2302 // ignore alpha for now..
2303 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2306 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2310 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2311 static void VM_SV_getsurfacenormal(void)
2314 msurface_t *surface;
2316 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal);
2317 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2318 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2320 // FIXME: implement rotation/scaling
2321 // note: this (incorrectly) assumes it is a simple polygon
2322 // note: this only returns the first triangle, so it doesn't work very
2323 // well for curved surfaces or arbitrary meshes
2324 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);
2325 VectorNormalize(normal);
2326 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2328 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2329 static void VM_SV_getsurfacetexture(void)
2332 msurface_t *surface;
2333 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture);
2334 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2335 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2337 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2339 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2340 static void VM_SV_getsurfacenearpoint(void)
2342 int surfacenum, best;
2344 vec_t dist, bestdist;
2347 msurface_t *surface;
2349 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint);
2350 PRVM_G_FLOAT(OFS_RETURN) = -1;
2351 ed = PRVM_G_EDICT(OFS_PARM0);
2352 point = PRVM_G_VECTOR(OFS_PARM1);
2354 if (!ed || ed->priv.server->free)
2356 model = getmodel(ed);
2357 if (!model || !model->num_surfaces)
2360 // FIXME: implement rotation/scaling
2361 VectorSubtract(point, ed->fields.server->origin, p);
2363 bestdist = 1000000000;
2364 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2366 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2367 // first see if the nearest point on the surface's box is closer than the previous match
2368 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2369 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2370 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2371 dist = VectorLength2(clipped);
2372 if (dist < bestdist)
2374 // it is, check the nearest point on the actual geometry
2375 clippointtosurface(model, surface, p, clipped);
2376 VectorSubtract(clipped, p, clipped);
2377 dist += VectorLength2(clipped);
2378 if (dist < bestdist)
2380 // that's closer too, store it as the best match
2386 PRVM_G_FLOAT(OFS_RETURN) = best;
2388 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2389 static void VM_SV_getsurfaceclippedpoint(void)
2393 msurface_t *surface;
2395 VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint);
2396 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2397 ed = PRVM_G_EDICT(OFS_PARM0);
2398 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2400 // FIXME: implement rotation/scaling
2401 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2402 clippointtosurface(model, surface, p, out);
2403 // FIXME: implement rotation/scaling
2404 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2407 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2408 //this function originally written by KrimZon, made shorter by LordHavoc
2409 static void VM_SV_clientcommand (void)
2411 client_t *temp_client;
2413 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2415 //find client for this entity
2416 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2417 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2419 Con_Print("PF_clientcommand: entity is not a client\n");
2423 temp_client = host_client;
2424 host_client = svs.clients + i;
2425 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2426 host_client = temp_client;
2429 //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)
2430 static void VM_SV_setattachment (void)
2432 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2433 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2434 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2438 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2440 if (e == prog->edicts)
2442 VM_Warning("setattachment: can not modify world entity\n");
2445 if (e->priv.server->free)
2447 VM_Warning("setattachment: can not modify free entity\n");
2451 if (tagentity == NULL)
2452 tagentity = prog->edicts;
2454 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2456 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2458 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2461 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2463 modelindex = (int)tagentity->fields.server->modelindex;
2464 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2466 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2468 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);
2471 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));
2475 /////////////////////////////////////////
2476 // DP_MD3_TAGINFO extension coded by VorteX
2478 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2483 i = (int)e->fields.server->modelindex;
2484 if (i < 1 || i >= MAX_MODELS)
2486 model = sv.models[i];
2488 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2491 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2493 float scale = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale)->_float;
2497 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);
2499 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);
2502 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2508 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2509 && (model = sv.models[(int)ent->fields.server->modelindex])
2510 && model->animscenes)
2512 // if model has wrong frame, engine automatically switches to model first frame
2513 frame = (int)ent->fields.server->frame;
2514 if (frame < 0 || frame >= model->numframes)
2516 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2518 *out = identitymatrix;
2522 // Warnings/errors code:
2523 // 0 - normal (everything all-right)
2526 // 3 - null or non-precached model
2527 // 4 - no tags with requested index
2528 // 5 - runaway loop at attachment chain
2529 extern cvar_t cl_bob;
2530 extern cvar_t cl_bobcycle;
2531 extern cvar_t cl_bobup;
2532 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2536 int modelindex, attachloop;
2537 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2540 *out = identitymatrix; // warnings and errors return identical matrix
2542 if (ent == prog->edicts)
2544 if (ent->priv.server->free)
2547 modelindex = (int)ent->fields.server->modelindex;
2548 if (modelindex <= 0 || modelindex > MAX_MODELS)
2551 model = sv.models[modelindex];
2553 tagmatrix = identitymatrix;
2554 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2558 if (attachloop >= 256) // prevent runaway looping
2560 // apply transformation by child's tagindex on parent entity and then
2561 // by parent entity itself
2562 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2563 if (ret && attachloop == 0)
2565 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2566 SV_GetEntityMatrix(ent, &entitymatrix, false);
2567 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2568 // next iteration we process the parent entity
2569 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2571 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2572 ent = PRVM_EDICT_NUM(val->edict);
2579 // RENDER_VIEWMODEL magic
2580 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2582 Matrix4x4_Copy(&tagmatrix, out);
2583 ent = PRVM_EDICT_NUM(val->edict);
2585 SV_GetEntityMatrix(ent, &entitymatrix, true);
2586 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2589 // Cl_bob, ported from rendering code
2590 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2593 // LordHavoc: this code is *weird*, but not replacable (I think it
2594 // should be done in QC on the server, but oh well, quake is quake)
2595 // LordHavoc: figured out bobup: the time at which the sin is at 180
2596 // degrees (which allows lengthening or squishing the peak or valley)
2597 cycle = sv.time/cl_bobcycle.value;
2598 cycle -= (int)cycle;
2599 if (cycle < cl_bobup.value)
2600 cycle = sin(M_PI * cycle / cl_bobup.value);
2602 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2603 // bob is proportional to velocity in the xy plane
2604 // (don't count Z, or jumping messes it up)
2605 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;
2606 bob = bob*0.3 + bob*0.7*cycle;
2607 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2614 //float(entity ent, string tagname) gettagindex;
2616 static void VM_SV_gettagindex (void)
2619 const char *tag_name;
2620 int modelindex, tag_index;
2622 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2624 ent = PRVM_G_EDICT(OFS_PARM0);
2625 tag_name = PRVM_G_STRING(OFS_PARM1);
2627 if (ent == prog->edicts)
2629 VM_Warning("gettagindex: can't affect world entity\n");
2632 if (ent->priv.server->free)
2634 VM_Warning("gettagindex: can't affect free entity\n");
2638 modelindex = (int)ent->fields.server->modelindex;
2640 if (modelindex <= 0 || modelindex > MAX_MODELS)
2641 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2644 tag_index = SV_GetTagIndex(ent, tag_name);
2646 if(developer.integer >= 100)
2647 Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2649 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2652 //vector(entity ent, float tagindex) gettaginfo;
2653 static void VM_SV_gettaginfo (void)
2657 matrix4x4_t tag_matrix;
2660 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2662 e = PRVM_G_EDICT(OFS_PARM0);
2663 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2665 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2666 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2671 VM_Warning("gettagindex: can't affect world entity\n");
2674 VM_Warning("gettagindex: can't affect free entity\n");
2677 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2680 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2683 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2688 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2689 static void VM_SV_dropclient (void)
2692 client_t *oldhostclient;
2693 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2694 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2695 if (clientnum < 0 || clientnum >= svs.maxclients)
2697 VM_Warning("dropclient: not a client\n");
2700 if (!svs.clients[clientnum].active)
2702 VM_Warning("dropclient: that client slot is not connected\n");
2705 oldhostclient = host_client;
2706 host_client = svs.clients + clientnum;
2707 SV_DropClient(false);
2708 host_client = oldhostclient;
2711 //entity() spawnclient (DP_SV_BOTCLIENT)
2712 static void VM_SV_spawnclient (void)
2716 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2717 prog->xfunction->builtinsprofile += 2;
2719 for (i = 0;i < svs.maxclients;i++)
2721 if (!svs.clients[i].active)
2723 prog->xfunction->builtinsprofile += 100;
2724 SV_ConnectClient (i, NULL);
2725 // this has to be set or else ClientDisconnect won't be called
2726 // we assume the qc will call ClientConnect...
2727 svs.clients[i].clientconnectcalled = true;
2728 ed = PRVM_EDICT_NUM(i + 1);
2732 VM_RETURN_EDICT(ed);
2735 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2736 static void VM_SV_clienttype (void)
2739 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2740 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2741 if (clientnum < 0 || clientnum >= svs.maxclients)
2742 PRVM_G_FLOAT(OFS_RETURN) = 3;
2743 else if (!svs.clients[clientnum].active)
2744 PRVM_G_FLOAT(OFS_RETURN) = 0;
2745 else if (svs.clients[clientnum].netconnection)
2746 PRVM_G_FLOAT(OFS_RETURN) = 1;
2748 PRVM_G_FLOAT(OFS_RETURN) = 2;
2755 string(string key) serverkey
2758 void VM_SV_serverkey(void)
2760 char string[VM_STRINGTEMP_LENGTH];
2761 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2762 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2763 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2766 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2767 static void VM_SV_setmodelindex (void)
2772 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2774 e = PRVM_G_EDICT(OFS_PARM0);
2775 if (e == prog->edicts)
2777 VM_Warning("setmodelindex: can not modify world entity\n");
2780 if (e->priv.server->free)
2782 VM_Warning("setmodelindex: can not modify free entity\n");
2785 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2786 if (i <= 0 || i > MAX_MODELS)
2788 VM_Warning("setmodelindex: invalid modelindex\n");
2791 if (!sv.model_precache[i][0])
2793 VM_Warning("setmodelindex: model not precached\n");
2797 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2798 e->fields.server->modelindex = i;
2804 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2805 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2807 SetMinMaxSize (e, quakemins, quakemaxs, true);
2810 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2813 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2814 static void VM_SV_modelnameforindex (void)
2817 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2819 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2821 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2822 if (i <= 0 || i > MAX_MODELS)
2824 VM_Warning("modelnameforindex: invalid modelindex\n");
2827 if (!sv.model_precache[i][0])
2829 VM_Warning("modelnameforindex: model not precached\n");
2833 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2836 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2837 static void VM_SV_particleeffectnum (void)
2840 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2841 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2844 PRVM_G_FLOAT(OFS_RETURN) = i;
2847 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2848 static void VM_SV_trailparticles (void)
2850 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2852 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2855 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2856 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2857 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2858 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2859 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2860 SV_FlushBroadcastMessages();
2863 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2864 static void VM_SV_pointparticles (void)
2866 int effectnum, count;
2868 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2870 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2873 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2874 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2875 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2876 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2877 if (count == 1 && !VectorLength2(vel))
2880 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2881 MSG_WriteShort(&sv.datagram, effectnum);
2882 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2886 // 1+2+12+12+2=29 bytes
2887 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2888 MSG_WriteShort(&sv.datagram, effectnum);
2889 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2890 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2891 MSG_WriteShort(&sv.datagram, count);
2894 SV_FlushBroadcastMessages();
2897 prvm_builtin_t vm_sv_builtins[] = {
2898 NULL, // #0 NULL function (not callable) (QUAKE)
2899 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
2900 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
2901 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
2902 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
2903 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
2904 VM_break, // #6 void() break (QUAKE)
2905 VM_random, // #7 float() random (QUAKE)
2906 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
2907 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
2908 VM_error, // #10 void(string e) error (QUAKE)
2909 VM_objerror, // #11 void(string e) objerror (QUAKE)
2910 VM_vlen, // #12 float(vector v) vlen (QUAKE)
2911 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
2912 VM_spawn, // #14 entity() spawn (QUAKE)
2913 VM_remove, // #15 void(entity e) remove (QUAKE)
2914 VM_SV_traceline, // #16 float(vector v1, vector v2, float tryents) traceline (QUAKE)
2915 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
2916 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
2917 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
2918 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
2919 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
2920 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
2921 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
2922 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
2923 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
2924 VM_ftos, // #26 string(float f) ftos (QUAKE)
2925 VM_vtos, // #27 string(vector v) vtos (QUAKE)
2926 VM_coredump, // #28 void() coredump (QUAKE)
2927 VM_traceon, // #29 void() traceon (QUAKE)
2928 VM_traceoff, // #30 void() traceoff (QUAKE)
2929 VM_eprint, // #31 void(entity e) eprint (QUAKE)
2930 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
2931 NULL, // #33 (QUAKE)
2932 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
2933 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
2934 VM_rint, // #36 float(float v) rint (QUAKE)
2935 VM_floor, // #37 float(float v) floor (QUAKE)
2936 VM_ceil, // #38 float(float v) ceil (QUAKE)
2937 NULL, // #39 (QUAKE)
2938 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
2939 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
2940 NULL, // #42 (QUAKE)
2941 VM_fabs, // #43 float(float f) fabs (QUAKE)
2942 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
2943 VM_cvar, // #45 float(string s) cvar (QUAKE)
2944 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
2945 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
2946 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
2947 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
2948 NULL, // #50 (QUAKE)
2949 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
2950 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
2951 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
2952 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
2953 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
2954 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
2955 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
2956 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
2957 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
2958 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
2959 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
2960 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
2961 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
2962 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
2963 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
2964 NULL, // #66 (QUAKE)
2965 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
2966 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
2967 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
2968 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
2969 NULL, // #71 (QUAKE)
2970 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
2971 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
2972 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
2973 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
2974 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
2975 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
2976 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
2977 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
2978 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
2979 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2980 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
2981 NULL, // #83 (QUAKE)
2982 NULL, // #84 (QUAKE)
2983 NULL, // #85 (QUAKE)
2984 NULL, // #86 (QUAKE)
2985 NULL, // #87 (QUAKE)
2986 NULL, // #88 (QUAKE)
2987 NULL, // #89 (QUAKE)
2988 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2989 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2990 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2991 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2992 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2993 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2994 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2995 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2996 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2997 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2998 // FrikaC and Telejano range #100-#199
3009 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3010 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3011 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3012 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3013 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3014 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3015 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3016 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3017 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3018 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3099 // FTEQW range #200-#299
3118 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3121 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3122 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3123 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3124 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3125 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3126 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3127 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3128 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3129 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3130 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3132 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3200 // CSQC range #300-#399
3201 NULL, // #300 void() clearscene (EXT_CSQC)
3202 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3203 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3204 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3205 NULL, // #304 void() renderscene (EXT_CSQC)
3206 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3207 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3208 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3209 NULL, // #308 void() R_EndPolygon
3211 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3212 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3216 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3217 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3218 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3219 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3220 NULL, // #319 void(string name) freepic (EXT_CSQC)
3221 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3222 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3223 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3224 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3225 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3226 NULL, // #325 void(void) drawresetcliparea
3231 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3232 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3233 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3234 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3235 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3236 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3237 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3238 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3239 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3240 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3241 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3242 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3243 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3244 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3245 NULL, // #344 vector() getmousepos (EXT_CSQC)
3246 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3247 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3248 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3249 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3250 NULL, // #349 float() isdemo (EXT_CSQC)
3251 VM_isserver, // #350 float() isserver (EXT_CSQC)
3252 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3253 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3254 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3255 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3261 NULL, // #360 float() readbyte (EXT_CSQC)
3262 NULL, // #361 float() readchar (EXT_CSQC)
3263 NULL, // #362 float() readshort (EXT_CSQC)
3264 NULL, // #363 float() readlong (EXT_CSQC)
3265 NULL, // #364 float() readcoord (EXT_CSQC)
3266 NULL, // #365 float() readangle (EXT_CSQC)
3267 NULL, // #366 string() readstring (EXT_CSQC)
3268 NULL, // #367 float() readfloat (EXT_CSQC)
3301 // LordHavoc's range #400-#499
3302 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3303 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3304 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3305 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3306 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3307 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3308 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3309 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3310 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)
3311 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3312 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3313 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3314 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3315 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3316 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3317 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3318 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3319 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3320 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3321 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3322 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3323 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3324 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3325 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3326 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3327 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3328 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3329 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3330 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3331 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3332 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3333 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3334 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3335 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3336 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3337 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3338 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3339 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3340 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3341 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3342 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3343 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3344 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3345 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3346 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3347 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3348 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3349 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3350 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3351 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3352 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3353 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3354 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3355 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3356 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3357 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3358 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3359 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3361 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3362 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3363 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3364 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3365 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3366 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3367 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3368 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3369 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3370 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3371 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3373 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3374 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3375 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3376 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3377 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3378 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3379 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3380 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3381 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3382 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3383 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3384 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3385 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3386 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3387 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3388 VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3396 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3397 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3398 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3399 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3400 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3401 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3402 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3403 VM_SV_WritePicture, // #501
3405 VM_whichpack, // #503 string(string) whichpack = #503;
3412 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3413 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3414 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3415 VM_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET)
3424 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3426 void VM_SV_Cmd_Init(void)
3431 void VM_SV_Cmd_Reset(void)
3433 if(prog->funcoffsets.SV_Shutdown)
3435 func_t s = prog->funcoffsets.SV_Shutdown;
3436 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3437 PRVM_ExecuteProgram(s,"SV_Shutdown() required");