5 //============================================================================
10 char *vm_sv_extensions =
15 "DP_CON_ALIASPARAMETERS "
33 "DP_ENT_CUSTOMCOLORMAP "
34 "DP_ENT_EXTERIORMODELTOCLIENT "
36 "DP_ENT_LOWPRECISION "
39 "DP_GFX_EXTERNALTEXTURES "
40 "DP_GFX_EXTERNALTEXTURES_PERMAP "
42 "DP_GFX_QUAKE3MODELTAGS "
46 "DP_HALFLIFE_MAP_CVAR "
52 "DP_MOVETYPEBOUNCEMISSILE "
54 "DP_QC_ASINACOSATANATAN2TAN "
57 "DP_QC_CVAR_DEFSTRING "
62 "DP_QC_FINDCHAINFLAGS "
63 "DP_QC_FINDCHAINFLOAT "
71 "DP_QC_MULTIPLETEMPSTRINGS "
73 "DP_QC_SINCOSSQRTPOW "
75 "DP_QC_STRING_CASE_FUNCTIONS "
76 "DP_QC_STRINGBUFFERS "
77 "DP_QC_STRINGCOLORFUNCTIONS "
78 "DP_QC_TOKENIZEBYSEPARATOR "
81 "DP_QC_TRACE_MOVETYPE_HITMODEL "
82 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
83 "DP_QC_UNLIMITEDTEMPSTRINGS "
84 "DP_QC_VECTOANGLES_WITH_ROLL "
85 "DP_QC_VECTORVECTORS "
91 "DP_SND_DIRECTIONLESSATTNNONE "
100 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
101 "DP_SV_DRAWONLYTOCLIENT "
104 "DP_SV_ENTITYCONTENTSTRANSITION "
105 "DP_SV_ONENTITYNOSPAWNFUNCTION "
106 "DP_SV_MODELFLAGS_AS_EFFECTS "
108 "DP_SV_NODRAWTOCLIENT "
110 "DP_SV_PLAYERPHYSICS "
111 "DP_SV_POINTPARTICLES "
113 "DP_SV_PRECACHEANYTIME "
116 "DP_SV_ROTATINGBMODEL "
119 "DP_SV_WRITEUNTERMINATEDSTRING "
123 "DP_TE_EXPLOSIONRGB "
125 "DP_TE_PARTICLECUBE "
126 "DP_TE_PARTICLERAIN "
127 "DP_TE_PARTICLESNOW "
129 "DP_TE_QUADEFFECTS1 "
132 "DP_TE_STANDARDEFFECTBUILTINS "
133 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
136 //"EXT_CSQC " // not ready yet
138 "KRIMZON_SV_PARSECLIENTCOMMAND "
141 "NEXUIZ_PLAYERMODEL "
143 "PRYDON_CLIENTCURSOR "
144 "TENEBRAE_GFX_DLIGHTS "
154 "DP_QC_GETSURFACEPOINTATTRIBUTE "
161 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.
163 setorigin (entity, origin)
166 static void VM_SV_setorigin (void)
171 VM_SAFEPARMCOUNT(2, VM_setorigin);
173 e = PRVM_G_EDICT(OFS_PARM0);
174 if (e == prog->edicts)
176 VM_Warning("setorigin: can not modify world entity\n");
179 if (e->priv.server->free)
181 VM_Warning("setorigin: can not modify free entity\n");
184 org = PRVM_G_VECTOR(OFS_PARM1);
185 VectorCopy (org, e->fields.server->origin);
186 SV_LinkEdict (e, false);
189 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
190 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
194 for (i=0 ; i<3 ; i++)
196 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
198 // set derived values
199 VectorCopy (min, e->fields.server->mins);
200 VectorCopy (max, e->fields.server->maxs);
201 VectorSubtract (max, min, e->fields.server->size);
203 SV_LinkEdict (e, false);
210 the size box is rotated by the current angle
211 LordHavoc: no it isn't...
213 setsize (entity, minvector, maxvector)
216 static void VM_SV_setsize (void)
221 VM_SAFEPARMCOUNT(3, VM_setsize);
223 e = PRVM_G_EDICT(OFS_PARM0);
224 if (e == prog->edicts)
226 VM_Warning("setsize: can not modify world entity\n");
229 if (e->priv.server->free)
231 VM_Warning("setsize: can not modify free entity\n");
234 min = PRVM_G_VECTOR(OFS_PARM1);
235 max = PRVM_G_VECTOR(OFS_PARM2);
236 SetMinMaxSize (e, min, max, false);
244 setmodel(entity, model)
247 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
248 static void VM_SV_setmodel (void)
254 VM_SAFEPARMCOUNT(2, VM_setmodel);
256 e = PRVM_G_EDICT(OFS_PARM0);
257 if (e == prog->edicts)
259 VM_Warning("setmodel: can not modify world entity\n");
262 if (e->priv.server->free)
264 VM_Warning("setmodel: can not modify free entity\n");
267 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
268 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
269 e->fields.server->modelindex = i;
275 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
276 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
278 SetMinMaxSize (e, quakemins, quakemaxs, true);
281 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
288 single print to a specific client
290 sprint(clientent, value)
293 static void VM_SV_sprint (void)
297 char string[VM_STRINGTEMP_LENGTH];
299 VM_VarString(1, string, sizeof(string));
301 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
303 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
304 // LordHavoc: div0 requested that sprintto world operate like print
311 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
313 VM_Warning("tried to centerprint to a non-client\n");
317 client = svs.clients + entnum-1;
318 if (!client->netconnection)
321 MSG_WriteChar(&client->netconnection->message,svc_print);
322 MSG_WriteString(&client->netconnection->message, string);
330 single print to a specific client
332 centerprint(clientent, value)
335 static void VM_SV_centerprint (void)
339 char string[VM_STRINGTEMP_LENGTH];
341 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
343 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
345 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
347 VM_Warning("tried to centerprint to a non-client\n");
351 client = svs.clients + entnum-1;
352 if (!client->netconnection)
355 VM_VarString(1, string, sizeof(string));
356 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
357 MSG_WriteString(&client->netconnection->message, string);
364 particle(origin, color, count)
367 static void VM_SV_particle (void)
373 VM_SAFEPARMCOUNT(4, VM_SV_particle);
375 org = PRVM_G_VECTOR(OFS_PARM0);
376 dir = PRVM_G_VECTOR(OFS_PARM1);
377 color = PRVM_G_FLOAT(OFS_PARM2);
378 count = PRVM_G_FLOAT(OFS_PARM3);
379 SV_StartParticle (org, dir, (int)color, (int)count);
389 static void VM_SV_ambientsound (void)
393 float vol, attenuation;
396 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
398 pos = PRVM_G_VECTOR (OFS_PARM0);
399 samp = PRVM_G_STRING(OFS_PARM1);
400 vol = PRVM_G_FLOAT(OFS_PARM2);
401 attenuation = PRVM_G_FLOAT(OFS_PARM3);
403 // check to see if samp was properly precached
404 soundnum = SV_SoundIndex(samp, 1);
412 // add an svc_spawnambient command to the level signon packet
415 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
417 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
419 MSG_WriteVector(&sv.signon, pos, sv.protocol);
421 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
422 MSG_WriteShort (&sv.signon, soundnum);
424 MSG_WriteByte (&sv.signon, soundnum);
426 MSG_WriteByte (&sv.signon, (int)(vol*255));
427 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
435 Each entity can have eight independant sound sources, like voice,
438 Channel 0 is an auto-allocate channel, the others override anything
439 already running on that entity/channel pair.
441 An attenuation of 0 will play full volume everywhere in the level.
442 Larger attenuations will drop off.
446 static void VM_SV_sound (void)
450 prvm_edict_t *entity;
454 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
456 entity = PRVM_G_EDICT(OFS_PARM0);
457 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
458 sample = PRVM_G_STRING(OFS_PARM2);
459 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
460 attenuation = PRVM_G_FLOAT(OFS_PARM4);
463 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
467 if (volume < 0 || volume > 255)
469 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
473 if (attenuation < 0 || attenuation > 4)
475 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
479 if (channel < 0 || channel > 7)
481 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
485 SV_StartSound (entity, channel, sample, volume, attenuation);
492 Follows the same logic as VM_SV_sound, except instead of
493 an entity, an origin for the sound is provided, and channel
494 is omitted (since no entity is being tracked).
498 static void VM_SV_pointsound(void)
505 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
507 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
508 sample = PRVM_G_STRING(OFS_PARM1);
509 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
510 attenuation = PRVM_G_FLOAT(OFS_PARM3);
512 if (volume < 0 || volume > 255)
514 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
518 if (attenuation < 0 || attenuation > 4)
520 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
524 SV_StartPointSound (org, sample, volume, attenuation);
531 Used for use tracing and shot targeting
532 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
533 if the tryents flag is set.
535 traceline (vector1, vector2, movetype, ignore)
538 static void VM_SV_traceline (void)
545 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
547 prog->xfunction->builtinsprofile += 30;
549 v1 = PRVM_G_VECTOR(OFS_PARM0);
550 v2 = PRVM_G_VECTOR(OFS_PARM1);
551 move = (int)PRVM_G_FLOAT(OFS_PARM2);
552 ent = PRVM_G_EDICT(OFS_PARM3);
554 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]))
555 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));
557 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
559 VM_SetTraceGlobals(&trace);
567 Used for use tracing and shot targeting
568 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
569 if the tryents flag is set.
571 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
574 // LordHavoc: added this for my own use, VERY useful, similar to traceline
575 static void VM_SV_tracebox (void)
577 float *v1, *v2, *m1, *m2;
582 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
584 prog->xfunction->builtinsprofile += 30;
586 v1 = PRVM_G_VECTOR(OFS_PARM0);
587 m1 = PRVM_G_VECTOR(OFS_PARM1);
588 m2 = PRVM_G_VECTOR(OFS_PARM2);
589 v2 = PRVM_G_VECTOR(OFS_PARM3);
590 move = (int)PRVM_G_FLOAT(OFS_PARM4);
591 ent = PRVM_G_EDICT(OFS_PARM5);
593 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]))
594 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));
596 trace = SV_Move (v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
598 VM_SetTraceGlobals(&trace);
601 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
606 vec3_t original_origin;
607 vec3_t original_velocity;
608 vec3_t original_angles;
609 vec3_t original_avelocity;
613 VectorCopy(tossent->fields.server->origin , original_origin );
614 VectorCopy(tossent->fields.server->velocity , original_velocity );
615 VectorCopy(tossent->fields.server->angles , original_angles );
616 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
618 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
619 if (val != NULL && val->_float != 0)
620 gravity = val->_float;
623 gravity *= sv_gravity.value * 0.05;
625 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
627 SV_CheckVelocity (tossent);
628 tossent->fields.server->velocity[2] -= gravity;
629 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
630 VectorScale (tossent->fields.server->velocity, 0.05, move);
631 VectorAdd (tossent->fields.server->origin, move, end);
632 trace = SV_Move (tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
633 VectorCopy (trace.endpos, tossent->fields.server->origin);
635 if (trace.fraction < 1)
639 VectorCopy(original_origin , tossent->fields.server->origin );
640 VectorCopy(original_velocity , tossent->fields.server->velocity );
641 VectorCopy(original_angles , tossent->fields.server->angles );
642 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
647 static void VM_SV_tracetoss (void)
651 prvm_edict_t *ignore;
653 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
655 prog->xfunction->builtinsprofile += 600;
657 ent = PRVM_G_EDICT(OFS_PARM0);
658 if (ent == prog->edicts)
660 VM_Warning("tracetoss: can not use world entity\n");
663 ignore = PRVM_G_EDICT(OFS_PARM1);
665 trace = SV_Trace_Toss (ent, ignore);
667 VM_SetTraceGlobals(&trace);
670 //============================================================================
672 static int checkpvsbytes;
673 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
675 static int VM_SV_newcheckclient (int check)
681 // cycle to the next one
683 check = bound(1, check, svs.maxclients);
684 if (check == svs.maxclients)
692 prog->xfunction->builtinsprofile++;
694 if (i == svs.maxclients+1)
696 // look up the client's edict
697 ent = PRVM_EDICT_NUM(i);
698 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
699 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
701 // found a valid client (possibly the same one again)
705 // get the PVS for the entity
706 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
708 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
709 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
718 Returns a client (or object that has a client enemy) that would be a
721 If there is more than one valid option, they are cycled each frame
723 If (self.origin + self.viewofs) is not in the PVS of the current target,
724 it is not returned at all.
729 int c_invis, c_notvis;
730 static void VM_SV_checkclient (void)
732 prvm_edict_t *ent, *self;
735 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
737 // find a new check if on a new frame
738 if (sv.time - sv.lastchecktime >= 0.1)
740 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
741 sv.lastchecktime = sv.time;
744 // return check if it might be visible
745 ent = PRVM_EDICT_NUM(sv.lastcheck);
746 if (ent->priv.server->free || ent->fields.server->health <= 0)
748 VM_RETURN_EDICT(prog->edicts);
752 // if current entity can't possibly see the check entity, return 0
753 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
754 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
755 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
758 VM_RETURN_EDICT(prog->edicts);
762 // might be able to see it
764 VM_RETURN_EDICT(ent);
767 //============================================================================
774 Sends text over to the client's execution buffer
776 stuffcmd (clientent, value, ...)
779 static void VM_SV_stuffcmd (void)
783 char string[VM_STRINGTEMP_LENGTH];
785 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
787 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
788 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
790 VM_Warning("Can't stuffcmd to a non-client\n");
794 VM_VarString(1, string, sizeof(string));
797 host_client = svs.clients + entnum-1;
798 Host_ClientCommands ("%s", string);
806 Returns a chain of entities that have origins within a spherical area
808 findradius (origin, radius)
811 static void VM_SV_findradius (void)
813 prvm_edict_t *ent, *chain;
814 vec_t radius, radius2;
815 vec3_t org, eorg, mins, maxs;
818 prvm_edict_t *touchedicts[MAX_EDICTS];
820 VM_SAFEPARMCOUNT(2, VM_SV_findradius);
822 chain = (prvm_edict_t *)prog->edicts;
824 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
825 radius = PRVM_G_FLOAT(OFS_PARM1);
826 radius2 = radius * radius;
828 mins[0] = org[0] - (radius + 1);
829 mins[1] = org[1] - (radius + 1);
830 mins[2] = org[2] - (radius + 1);
831 maxs[0] = org[0] + (radius + 1);
832 maxs[1] = org[1] + (radius + 1);
833 maxs[2] = org[2] + (radius + 1);
834 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
835 if (numtouchedicts > MAX_EDICTS)
837 // this never happens
838 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
839 numtouchedicts = MAX_EDICTS;
841 for (i = 0;i < numtouchedicts;i++)
843 ent = touchedicts[i];
844 prog->xfunction->builtinsprofile++;
845 // Quake did not return non-solid entities but darkplaces does
846 // (note: this is the reason you can't blow up fallen zombies)
847 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
849 // LordHavoc: compare against bounding box rather than center so it
850 // doesn't miss large objects, and use DotProduct instead of Length
851 // for a major speedup
852 VectorSubtract(org, ent->fields.server->origin, eorg);
853 if (sv_gameplayfix_findradiusdistancetobox.integer)
855 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
856 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
857 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
860 VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
861 if (DotProduct(eorg, eorg) < radius2)
863 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
868 VM_RETURN_EDICT(chain);
871 static void VM_SV_precache_sound (void)
873 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
874 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
877 static void VM_SV_precache_model (void)
879 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
880 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
881 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
888 float(float yaw, float dist[, settrace]) walkmove
891 static void VM_SV_walkmove (void)
900 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
902 // assume failure if it returns early
903 PRVM_G_FLOAT(OFS_RETURN) = 0;
905 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
906 if (ent == prog->edicts)
908 VM_Warning("walkmove: can not modify world entity\n");
911 if (ent->priv.server->free)
913 VM_Warning("walkmove: can not modify free entity\n");
916 yaw = PRVM_G_FLOAT(OFS_PARM0);
917 dist = PRVM_G_FLOAT(OFS_PARM1);
918 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
920 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
923 yaw = yaw*M_PI*2 / 360;
925 move[0] = cos(yaw)*dist;
926 move[1] = sin(yaw)*dist;
929 // save program state, because SV_movestep may call other progs
930 oldf = prog->xfunction;
931 oldself = prog->globals.server->self;
933 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
936 // restore program state
937 prog->xfunction = oldf;
938 prog->globals.server->self = oldself;
948 static void VM_SV_droptofloor (void)
954 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
956 // assume failure if it returns early
957 PRVM_G_FLOAT(OFS_RETURN) = 0;
959 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
960 if (ent == prog->edicts)
962 VM_Warning("droptofloor: can not modify world entity\n");
965 if (ent->priv.server->free)
967 VM_Warning("droptofloor: can not modify free entity\n");
971 VectorCopy (ent->fields.server->origin, end);
974 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
975 SV_UnstickEntity(ent);
977 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
978 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
981 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]);
982 VectorAdd(ent->fields.server->origin, offset, org);
983 trace = SV_Move (org, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
984 VectorSubtract(trace.endpos, offset, trace.endpos);
985 if (trace.startsolid)
987 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]);
988 SV_UnstickEntity(ent);
989 SV_LinkEdict (ent, false);
990 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
991 ent->fields.server->groundentity = 0;
992 PRVM_G_FLOAT(OFS_RETURN) = 1;
994 else if (trace.fraction < 1)
996 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]);
997 VectorCopy (trace.endpos, ent->fields.server->origin);
998 SV_UnstickEntity(ent);
999 SV_LinkEdict (ent, false);
1000 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1001 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1002 PRVM_G_FLOAT(OFS_RETURN) = 1;
1003 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1004 ent->priv.server->suspendedinairflag = true;
1009 if (trace.fraction != 1)
1011 if (trace.fraction < 1)
1012 VectorCopy (trace.endpos, ent->fields.server->origin);
1013 SV_LinkEdict (ent, false);
1014 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1015 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1016 PRVM_G_FLOAT(OFS_RETURN) = 1;
1017 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1018 ent->priv.server->suspendedinairflag = true;
1027 void(float style, string value) lightstyle
1030 static void VM_SV_lightstyle (void)
1037 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1039 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1040 val = PRVM_G_STRING(OFS_PARM1);
1042 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1043 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1046 // change the string in sv
1047 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1049 // send message to all clients on this server
1050 if (sv.state != ss_active)
1053 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1055 if (client->active && client->netconnection)
1057 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1058 MSG_WriteChar (&client->netconnection->message,style);
1059 MSG_WriteString (&client->netconnection->message, val);
1069 static void VM_SV_checkbottom (void)
1071 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1072 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1080 static void VM_SV_pointcontents (void)
1082 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1083 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1090 Pick a vector for the player to shoot along
1091 vector aim(entity, missilespeed)
1094 static void VM_SV_aim (void)
1096 prvm_edict_t *ent, *check, *bestent;
1097 vec3_t start, dir, end, bestdir;
1100 float dist, bestdist;
1103 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1105 // assume failure if it returns early
1106 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1107 // if sv_aim is so high it can't possibly accept anything, skip out early
1108 if (sv_aim.value >= 1)
1111 ent = PRVM_G_EDICT(OFS_PARM0);
1112 if (ent == prog->edicts)
1114 VM_Warning("aim: can not use world entity\n");
1117 if (ent->priv.server->free)
1119 VM_Warning("aim: can not use free entity\n");
1122 speed = PRVM_G_FLOAT(OFS_PARM1);
1124 VectorCopy (ent->fields.server->origin, start);
1127 // try sending a trace straight
1128 VectorCopy (prog->globals.server->v_forward, dir);
1129 VectorMA (start, 2048, dir, end);
1130 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1131 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1132 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1134 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1139 // try all possible entities
1140 VectorCopy (dir, bestdir);
1141 bestdist = sv_aim.value;
1144 check = PRVM_NEXT_EDICT(prog->edicts);
1145 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1147 prog->xfunction->builtinsprofile++;
1148 if (check->fields.server->takedamage != DAMAGE_AIM)
1152 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1153 continue; // don't aim at teammate
1154 for (j=0 ; j<3 ; j++)
1155 end[j] = check->fields.server->origin[j]
1156 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1157 VectorSubtract (end, start, dir);
1158 VectorNormalize (dir);
1159 dist = DotProduct (dir, prog->globals.server->v_forward);
1160 if (dist < bestdist)
1161 continue; // to far to turn
1162 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1163 if (tr.ent == check)
1164 { // can shoot at this one
1172 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1173 dist = DotProduct (dir, prog->globals.server->v_forward);
1174 VectorScale (prog->globals.server->v_forward, dist, end);
1176 VectorNormalize (end);
1177 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1181 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1186 ===============================================================================
1190 ===============================================================================
1193 #define MSG_BROADCAST 0 // unreliable to all
1194 #define MSG_ONE 1 // reliable to one (msg_entity)
1195 #define MSG_ALL 2 // reliable to all
1196 #define MSG_INIT 3 // write to the init string
1197 #define MSG_ENTITY 5
1199 sizebuf_t *WriteDest (void)
1205 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1209 return &sv.datagram;
1212 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1213 entnum = PRVM_NUM_FOR_EDICT(ent);
1214 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1216 VM_Warning ("WriteDest: tried to write to non-client\n");
1217 return &sv.reliable_datagram;
1220 return &svs.clients[entnum-1].netconnection->message;
1223 VM_Warning ("WriteDest: bad destination\n");
1225 return &sv.reliable_datagram;
1231 return sv.writeentitiestoclient_msg;
1237 static void VM_SV_WriteByte (void)
1239 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1240 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1243 static void VM_SV_WriteChar (void)
1245 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1246 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1249 static void VM_SV_WriteShort (void)
1251 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1252 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1255 static void VM_SV_WriteLong (void)
1257 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1258 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1261 static void VM_SV_WriteAngle (void)
1263 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1264 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1267 static void VM_SV_WriteCoord (void)
1269 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1270 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1273 static void VM_SV_WriteString (void)
1275 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1276 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1279 static void VM_SV_WriteUnterminatedString (void)
1281 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1282 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1286 static void VM_SV_WriteEntity (void)
1288 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1289 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1292 //////////////////////////////////////////////////////////
1294 static void VM_SV_makestatic (void)
1299 // allow 0 parameters due to an id1 qc bug in which this function is used
1300 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1301 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1303 if (prog->argc >= 1)
1304 ent = PRVM_G_EDICT(OFS_PARM0);
1306 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1307 if (ent == prog->edicts)
1309 VM_Warning("makestatic: can not modify world entity\n");
1312 if (ent->priv.server->free)
1314 VM_Warning("makestatic: can not modify free entity\n");
1319 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1324 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1325 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1326 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1328 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1330 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1331 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1332 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1336 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1337 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1338 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1341 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1342 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1343 for (i=0 ; i<3 ; i++)
1345 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1346 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1349 // throw the entity away now
1353 //=============================================================================
1360 static void VM_SV_setspawnparms (void)
1366 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1368 ent = PRVM_G_EDICT(OFS_PARM0);
1369 i = PRVM_NUM_FOR_EDICT(ent);
1370 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1372 Con_Print("tried to setspawnparms on a non-client\n");
1376 // copy spawn parms out of the client_t
1377 client = svs.clients + i-1;
1378 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1379 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1386 Returns a color vector indicating the lighting at the requested point.
1388 (Internal Operation note: actually measures the light beneath the point, just like
1389 the model lighting on the client)
1394 static void VM_SV_getlight (void)
1396 vec3_t ambientcolor, diffusecolor, diffusenormal;
1398 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1399 p = PRVM_G_VECTOR(OFS_PARM0);
1400 VectorClear(ambientcolor);
1401 VectorClear(diffusecolor);
1402 VectorClear(diffusenormal);
1403 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1404 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1405 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1410 unsigned char type; // 1/2/8 or other value if isn't used
1414 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1415 static int vm_customstats_last;
1417 void VM_CustomStats_Clear (void)
1421 Z_Free(vm_customstats);
1422 vm_customstats = NULL;
1423 vm_customstats_last = -1;
1427 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1435 for(i=0; i<vm_customstats_last+1 ;i++)
1437 if(!vm_customstats[i].type)
1439 switch(vm_customstats[i].type)
1441 //string as 16 bytes
1444 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1445 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1446 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1447 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1448 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1450 //float field sent as-is
1452 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1454 //integer value of float field
1456 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1464 // void(float index, float type, .void field) SV_AddStat = #232;
1465 // Set up an auto-sent player stat.
1466 // Client's get thier own fields sent to them. Index may not be less than 32.
1467 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1468 // 1: string (4 stats carrying a total of 16 charactures)
1469 // 2: float (one stat, float converted to an integer for transportation)
1470 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1471 static void VM_SV_AddStat (void)
1476 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1480 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1483 VM_Warning("PF_SV_AddStat: not enough memory\n");
1487 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1488 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1489 off = PRVM_G_INT (OFS_PARM2);
1494 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1497 if(i >= (MAX_CL_STATS-32))
1499 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1502 if(i > (MAX_CL_STATS-32-4) && type == 1)
1504 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1507 vm_customstats[i].type = type;
1508 vm_customstats[i].fieldoffset = off;
1509 if(vm_customstats_last < i)
1510 vm_customstats_last = i;
1517 copies data from one entity to another
1519 copyentity(src, dst)
1522 static void VM_SV_copyentity (void)
1524 prvm_edict_t *in, *out;
1525 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1526 in = PRVM_G_EDICT(OFS_PARM0);
1527 if (in == prog->edicts)
1529 VM_Warning("copyentity: can not read world entity\n");
1532 if (in->priv.server->free)
1534 VM_Warning("copyentity: can not read free entity\n");
1537 out = PRVM_G_EDICT(OFS_PARM1);
1538 if (out == prog->edicts)
1540 VM_Warning("copyentity: can not modify world entity\n");
1543 if (out->priv.server->free)
1545 VM_Warning("copyentity: can not modify free entity\n");
1548 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1549 SV_LinkEdict(out, false);
1557 sets the color of a client and broadcasts the update to all connected clients
1559 setcolor(clientent, value)
1562 static void VM_SV_setcolor (void)
1568 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1569 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1570 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1572 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1574 Con_Print("tried to setcolor a non-client\n");
1578 client = svs.clients + entnum-1;
1581 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1583 client->edict->fields.server->team = (i & 15) + 1;
1586 if (client->old_colors != client->colors)
1588 client->old_colors = client->colors;
1589 // send notification to all clients
1590 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1591 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1592 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1600 effect(origin, modelname, startframe, framecount, framerate)
1603 static void VM_SV_effect (void)
1607 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1608 s = PRVM_G_STRING(OFS_PARM1);
1611 VM_Warning("effect: no model specified\n");
1615 i = SV_ModelIndex(s, 1);
1618 VM_Warning("effect: model not precached\n");
1622 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1624 VM_Warning("effect: framecount < 1\n");
1628 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1630 VM_Warning("effect: framerate < 1\n");
1634 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));
1637 static void VM_SV_te_blood (void)
1639 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1640 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1642 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1643 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1645 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1646 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1647 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1649 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1650 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1651 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1653 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1654 SV_FlushBroadcastMessages();
1657 static void VM_SV_te_bloodshower (void)
1659 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1660 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1662 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1663 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1665 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1666 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1667 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1669 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1670 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1671 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1673 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1675 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1676 SV_FlushBroadcastMessages();
1679 static void VM_SV_te_explosionrgb (void)
1681 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1682 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1683 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1685 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1686 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1687 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1689 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1690 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1691 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1692 SV_FlushBroadcastMessages();
1695 static void VM_SV_te_particlecube (void)
1697 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1698 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1700 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1701 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1703 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1704 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1705 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1707 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1708 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1709 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1711 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1712 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1713 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1715 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1717 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1718 // gravity true/false
1719 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1721 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1722 SV_FlushBroadcastMessages();
1725 static void VM_SV_te_particlerain (void)
1727 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1728 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1730 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1731 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1733 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1734 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1735 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1737 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1738 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1739 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1741 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1742 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1743 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1745 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1747 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1748 SV_FlushBroadcastMessages();
1751 static void VM_SV_te_particlesnow (void)
1753 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1754 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1756 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1757 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1759 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1760 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1761 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1763 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1764 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1765 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1767 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1768 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1769 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1771 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1773 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1774 SV_FlushBroadcastMessages();
1777 static void VM_SV_te_spark (void)
1779 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1780 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1782 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1783 MSG_WriteByte(&sv.datagram, TE_SPARK);
1785 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1786 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1787 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1789 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1790 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1791 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1793 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1794 SV_FlushBroadcastMessages();
1797 static void VM_SV_te_gunshotquad (void)
1799 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1800 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1801 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
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);
1806 SV_FlushBroadcastMessages();
1809 static void VM_SV_te_spikequad (void)
1811 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1812 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1813 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1815 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1816 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1817 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1818 SV_FlushBroadcastMessages();
1821 static void VM_SV_te_superspikequad (void)
1823 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1824 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1825 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1827 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1828 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1830 SV_FlushBroadcastMessages();
1833 static void VM_SV_te_explosionquad (void)
1835 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
1836 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1837 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1839 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1840 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1841 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1842 SV_FlushBroadcastMessages();
1845 static void VM_SV_te_smallflash (void)
1847 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
1848 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1849 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1851 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1852 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1853 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1854 SV_FlushBroadcastMessages();
1857 static void VM_SV_te_customflash (void)
1859 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
1860 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1862 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1863 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1865 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1866 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1869 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1871 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1873 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1874 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1875 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1876 SV_FlushBroadcastMessages();
1879 static void VM_SV_te_gunshot (void)
1881 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
1882 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1883 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1885 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1886 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1887 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1888 SV_FlushBroadcastMessages();
1891 static void VM_SV_te_spike (void)
1893 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
1894 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1895 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1900 SV_FlushBroadcastMessages();
1903 static void VM_SV_te_superspike (void)
1905 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
1906 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1907 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
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);
1912 SV_FlushBroadcastMessages();
1915 static void VM_SV_te_explosion (void)
1917 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
1918 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1919 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1921 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1922 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1923 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1924 SV_FlushBroadcastMessages();
1927 static void VM_SV_te_tarexplosion (void)
1929 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
1930 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1931 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1934 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1936 SV_FlushBroadcastMessages();
1939 static void VM_SV_te_wizspike (void)
1941 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
1942 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1943 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1945 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1948 SV_FlushBroadcastMessages();
1951 static void VM_SV_te_knightspike (void)
1953 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
1954 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1955 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1960 SV_FlushBroadcastMessages();
1963 static void VM_SV_te_lavasplash (void)
1965 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
1966 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1967 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1970 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1972 SV_FlushBroadcastMessages();
1975 static void VM_SV_te_teleport (void)
1977 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
1978 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1979 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1983 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1984 SV_FlushBroadcastMessages();
1987 static void VM_SV_te_explosion2 (void)
1989 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
1990 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1991 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1993 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1994 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1995 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1997 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
1998 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
1999 SV_FlushBroadcastMessages();
2002 static void VM_SV_te_lightning1 (void)
2004 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2005 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2006 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2008 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2010 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2011 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2012 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2014 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2015 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2016 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2017 SV_FlushBroadcastMessages();
2020 static void VM_SV_te_lightning2 (void)
2022 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2023 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2024 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2026 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2028 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2029 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2030 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2032 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2033 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2034 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2035 SV_FlushBroadcastMessages();
2038 static void VM_SV_te_lightning3 (void)
2040 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2041 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2042 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2044 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2046 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2047 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2048 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2050 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2052 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2053 SV_FlushBroadcastMessages();
2056 static void VM_SV_te_beam (void)
2058 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2059 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2060 MSG_WriteByte(&sv.datagram, TE_BEAM);
2062 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2064 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2065 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2066 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2068 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2069 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2070 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2071 SV_FlushBroadcastMessages();
2074 static void VM_SV_te_plasmaburn (void)
2076 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2077 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2078 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2079 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2080 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2081 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2082 SV_FlushBroadcastMessages();
2085 static void VM_SV_te_flamejet (void)
2087 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2088 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2089 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2091 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2092 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2093 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2095 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2096 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2097 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2099 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2100 SV_FlushBroadcastMessages();
2103 void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2106 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2108 bestdist = 1000000000;
2110 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2112 // clip original point to each triangle of the surface and find the
2113 // triangle that is closest
2114 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2115 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2116 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2117 TriangleNormal(v[0], v[1], v[2], facenormal);
2118 VectorNormalize(facenormal);
2119 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2120 VectorMA(p, offsetdist, facenormal, temp);
2121 for (j = 0, k = 2;j < 3;k = j, j++)
2123 VectorSubtract(v[k], v[j], edgenormal);
2124 CrossProduct(edgenormal, facenormal, sidenormal);
2125 VectorNormalize(sidenormal);
2126 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2128 VectorMA(temp, offsetdist, sidenormal, temp);
2130 dist = VectorDistance2(temp, p);
2131 if (bestdist > dist)
2134 VectorCopy(temp, out);
2139 static model_t *getmodel(prvm_edict_t *ed)
2142 if (!ed || ed->priv.server->free)
2144 modelindex = (int)ed->fields.server->modelindex;
2145 if (modelindex < 1 || modelindex >= MAX_MODELS)
2147 return sv.models[modelindex];
2150 static msurface_t *getsurface(model_t *model, int surfacenum)
2152 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2154 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2158 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2159 static void VM_SV_getsurfacenumpoints(void)
2162 msurface_t *surface;
2163 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints);
2164 // return 0 if no such surface
2165 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2167 PRVM_G_FLOAT(OFS_RETURN) = 0;
2171 // note: this (incorrectly) assumes it is a simple polygon
2172 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2174 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2175 static void VM_SV_getsurfacepoint(void)
2179 msurface_t *surface;
2181 VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint);
2182 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2183 ed = PRVM_G_EDICT(OFS_PARM0);
2184 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2186 // note: this (incorrectly) assumes it is a simple polygon
2187 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2188 if (pointnum < 0 || pointnum >= surface->num_vertices)
2190 // FIXME: implement rotation/scaling
2191 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2193 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
2194 // float SPA_POSITION = 0;
2195 // float SPA_S_AXIS = 1;
2196 // float SPA_T_AXIS = 2;
2197 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2198 // float SPA_TEXCOORDS0 = 4;
2199 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2200 // float SPA_LIGHTMAP0_COLOR = 6;
2201 static void VM_SV_getsurfacepointattribute(void)
2205 msurface_t *surface;
2209 VM_SAFEPARMCOUNT(4, VM_SV_getsurfacepoint);
2210 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2211 ed = PRVM_G_EDICT(OFS_PARM0);
2212 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2214 // note: this (incorrectly) assumes it is a simple polygon
2215 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2216 if (pointnum < 0 || pointnum >= surface->num_vertices)
2218 // FIXME: implement rotation/scaling
2219 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
2221 switch( attributetype ) {
2222 // float SPA_POSITION = 0;
2224 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2226 // float SPA_S_AXIS = 1;
2228 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2230 // float SPA_T_AXIS = 2;
2232 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2234 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2236 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2238 // float SPA_TEXCOORDS0 = 4;
2240 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2241 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
2242 ret[0] = texcoord[0];
2243 ret[1] = texcoord[1];
2247 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2249 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2250 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
2251 ret[0] = texcoord[0];
2252 ret[1] = texcoord[1];
2256 // float SPA_LIGHTMAP0_COLOR = 6;
2258 // ignore alpha for now..
2259 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2262 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2266 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2267 static void VM_SV_getsurfacenormal(void)
2270 msurface_t *surface;
2272 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal);
2273 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2274 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2276 // FIXME: implement rotation/scaling
2277 // note: this (incorrectly) assumes it is a simple polygon
2278 // note: this only returns the first triangle, so it doesn't work very
2279 // well for curved surfaces or arbitrary meshes
2280 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);
2281 VectorNormalize(normal);
2282 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2284 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2285 static void VM_SV_getsurfacetexture(void)
2288 msurface_t *surface;
2289 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture);
2290 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2291 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2293 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2295 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2296 static void VM_SV_getsurfacenearpoint(void)
2298 int surfacenum, best;
2300 vec_t dist, bestdist;
2303 msurface_t *surface;
2305 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint);
2306 PRVM_G_FLOAT(OFS_RETURN) = -1;
2307 ed = PRVM_G_EDICT(OFS_PARM0);
2308 point = PRVM_G_VECTOR(OFS_PARM1);
2310 if (!ed || ed->priv.server->free)
2312 model = getmodel(ed);
2313 if (!model || !model->num_surfaces)
2316 // FIXME: implement rotation/scaling
2317 VectorSubtract(point, ed->fields.server->origin, p);
2319 bestdist = 1000000000;
2320 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2322 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2323 // first see if the nearest point on the surface's box is closer than the previous match
2324 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2325 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2326 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2327 dist = VectorLength2(clipped);
2328 if (dist < bestdist)
2330 // it is, check the nearest point on the actual geometry
2331 clippointtosurface(model, surface, p, clipped);
2332 VectorSubtract(clipped, p, clipped);
2333 dist += VectorLength2(clipped);
2334 if (dist < bestdist)
2336 // that's closer too, store it as the best match
2342 PRVM_G_FLOAT(OFS_RETURN) = best;
2344 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2345 static void VM_SV_getsurfaceclippedpoint(void)
2349 msurface_t *surface;
2351 VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint);
2352 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2353 ed = PRVM_G_EDICT(OFS_PARM0);
2354 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2356 // FIXME: implement rotation/scaling
2357 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2358 clippointtosurface(model, surface, p, out);
2359 // FIXME: implement rotation/scaling
2360 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2363 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2364 //this function originally written by KrimZon, made shorter by LordHavoc
2365 static void VM_SV_clientcommand (void)
2367 client_t *temp_client;
2369 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2371 //find client for this entity
2372 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2373 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2375 Con_Print("PF_clientcommand: entity is not a client\n");
2379 temp_client = host_client;
2380 host_client = svs.clients + i;
2381 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2382 host_client = temp_client;
2385 //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)
2386 static void VM_SV_setattachment (void)
2388 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2389 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2390 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2394 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2396 if (e == prog->edicts)
2398 VM_Warning("setattachment: can not modify world entity\n");
2401 if (e->priv.server->free)
2403 VM_Warning("setattachment: can not modify free entity\n");
2407 if (tagentity == NULL)
2408 tagentity = prog->edicts;
2410 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2412 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2414 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2417 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2419 modelindex = (int)tagentity->fields.server->modelindex;
2420 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2422 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2424 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);
2427 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));
2431 /////////////////////////////////////////
2432 // DP_MD3_TAGINFO extension coded by VorteX
2434 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2439 i = (int)e->fields.server->modelindex;
2440 if (i < 1 || i >= MAX_MODELS)
2442 model = sv.models[i];
2444 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2447 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2449 float scale = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale)->_float;
2453 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);
2455 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);
2458 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2464 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2465 && (model = sv.models[(int)ent->fields.server->modelindex])
2466 && model->animscenes)
2468 // if model has wrong frame, engine automatically switches to model first frame
2469 frame = (int)ent->fields.server->frame;
2470 if (frame < 0 || frame >= model->numframes)
2472 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2474 *out = identitymatrix;
2478 // Warnings/errors code:
2479 // 0 - normal (everything all-right)
2482 // 3 - null or non-precached model
2483 // 4 - no tags with requested index
2484 // 5 - runaway loop at attachment chain
2485 extern cvar_t cl_bob;
2486 extern cvar_t cl_bobcycle;
2487 extern cvar_t cl_bobup;
2488 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2492 int modelindex, attachloop;
2493 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2496 *out = identitymatrix; // warnings and errors return identical matrix
2498 if (ent == prog->edicts)
2500 if (ent->priv.server->free)
2503 modelindex = (int)ent->fields.server->modelindex;
2504 if (modelindex <= 0 || modelindex > MAX_MODELS)
2507 model = sv.models[modelindex];
2509 tagmatrix = identitymatrix;
2510 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2514 if (attachloop >= 256) // prevent runaway looping
2516 // apply transformation by child's tagindex on parent entity and then
2517 // by parent entity itself
2518 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2519 if (ret && attachloop == 0)
2521 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2522 SV_GetEntityMatrix(ent, &entitymatrix, false);
2523 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2524 // next iteration we process the parent entity
2525 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2527 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2528 ent = PRVM_EDICT_NUM(val->edict);
2535 // RENDER_VIEWMODEL magic
2536 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2538 Matrix4x4_Copy(&tagmatrix, out);
2539 ent = PRVM_EDICT_NUM(val->edict);
2541 SV_GetEntityMatrix(ent, &entitymatrix, true);
2542 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2545 // Cl_bob, ported from rendering code
2546 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2549 // LordHavoc: this code is *weird*, but not replacable (I think it
2550 // should be done in QC on the server, but oh well, quake is quake)
2551 // LordHavoc: figured out bobup: the time at which the sin is at 180
2552 // degrees (which allows lengthening or squishing the peak or valley)
2553 cycle = sv.time/cl_bobcycle.value;
2554 cycle -= (int)cycle;
2555 if (cycle < cl_bobup.value)
2556 cycle = sin(M_PI * cycle / cl_bobup.value);
2558 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2559 // bob is proportional to velocity in the xy plane
2560 // (don't count Z, or jumping messes it up)
2561 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;
2562 bob = bob*0.3 + bob*0.7*cycle;
2563 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2570 //float(entity ent, string tagname) gettagindex;
2572 static void VM_SV_gettagindex (void)
2575 const char *tag_name;
2576 int modelindex, tag_index;
2578 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2580 ent = PRVM_G_EDICT(OFS_PARM0);
2581 tag_name = PRVM_G_STRING(OFS_PARM1);
2583 if (ent == prog->edicts)
2585 VM_Warning("gettagindex: can't affect world entity\n");
2588 if (ent->priv.server->free)
2590 VM_Warning("gettagindex: can't affect free entity\n");
2594 modelindex = (int)ent->fields.server->modelindex;
2596 if (modelindex <= 0 || modelindex > MAX_MODELS)
2597 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2600 tag_index = SV_GetTagIndex(ent, tag_name);
2602 if(developer.integer >= 100)
2603 Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2605 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2608 //vector(entity ent, float tagindex) gettaginfo;
2609 static void VM_SV_gettaginfo (void)
2613 matrix4x4_t tag_matrix;
2616 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2618 e = PRVM_G_EDICT(OFS_PARM0);
2619 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2621 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2622 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2627 VM_Warning("gettagindex: can't affect world entity\n");
2630 VM_Warning("gettagindex: can't affect free entity\n");
2633 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2636 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2639 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2644 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2645 static void VM_SV_dropclient (void)
2648 client_t *oldhostclient;
2649 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2650 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2651 if (clientnum < 0 || clientnum >= svs.maxclients)
2653 VM_Warning("dropclient: not a client\n");
2656 if (!svs.clients[clientnum].active)
2658 VM_Warning("dropclient: that client slot is not connected\n");
2661 oldhostclient = host_client;
2662 host_client = svs.clients + clientnum;
2663 SV_DropClient(false);
2664 host_client = oldhostclient;
2667 //entity() spawnclient (DP_SV_BOTCLIENT)
2668 static void VM_SV_spawnclient (void)
2672 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2673 prog->xfunction->builtinsprofile += 2;
2675 for (i = 0;i < svs.maxclients;i++)
2677 if (!svs.clients[i].active)
2679 prog->xfunction->builtinsprofile += 100;
2680 SV_ConnectClient (i, NULL);
2681 // this has to be set or else ClientDisconnect won't be called
2682 // we assume the qc will call ClientConnect...
2683 svs.clients[i].clientconnectcalled = true;
2684 ed = PRVM_EDICT_NUM(i + 1);
2688 VM_RETURN_EDICT(ed);
2691 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2692 static void VM_SV_clienttype (void)
2695 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2696 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2697 if (clientnum < 0 || clientnum >= svs.maxclients)
2698 PRVM_G_FLOAT(OFS_RETURN) = 3;
2699 else if (!svs.clients[clientnum].active)
2700 PRVM_G_FLOAT(OFS_RETURN) = 0;
2701 else if (svs.clients[clientnum].netconnection)
2702 PRVM_G_FLOAT(OFS_RETURN) = 1;
2704 PRVM_G_FLOAT(OFS_RETURN) = 2;
2711 string(string key) serverkey
2714 void VM_SV_serverkey(void)
2716 char string[VM_STRINGTEMP_LENGTH];
2717 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2718 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2719 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2722 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2723 static void VM_SV_setmodelindex (void)
2728 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2730 e = PRVM_G_EDICT(OFS_PARM0);
2731 if (e == prog->edicts)
2733 VM_Warning("setmodelindex: can not modify world entity\n");
2736 if (e->priv.server->free)
2738 VM_Warning("setmodelindex: can not modify free entity\n");
2741 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2742 if (i <= 0 || i > MAX_MODELS)
2744 VM_Warning("setmodelindex: invalid modelindex\n");
2747 if (!sv.model_precache[i][0])
2749 VM_Warning("setmodelindex: model not precached\n");
2753 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2754 e->fields.server->modelindex = i;
2760 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2761 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2763 SetMinMaxSize (e, quakemins, quakemaxs, true);
2766 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2769 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2770 static void VM_SV_modelnameforindex (void)
2773 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2775 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2777 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2778 if (i <= 0 || i > MAX_MODELS)
2780 VM_Warning("modelnameforindex: invalid modelindex\n");
2783 if (!sv.model_precache[i][0])
2785 VM_Warning("modelnameforindex: model not precached\n");
2789 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2792 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2793 static void VM_SV_particleeffectnum (void)
2796 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2797 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2800 PRVM_G_FLOAT(OFS_RETURN) = i;
2803 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2804 static void VM_SV_trailparticles (void)
2806 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2808 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2809 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2810 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2811 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2812 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2813 SV_FlushBroadcastMessages();
2816 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2817 static void VM_SV_pointparticles (void)
2819 int effectnum, count;
2821 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2822 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2823 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2824 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2825 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2826 if (count == 1 && !VectorLength2(vel))
2829 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2830 MSG_WriteShort(&sv.datagram, effectnum);
2831 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2835 // 1+2+12+12+2=29 bytes
2836 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2837 MSG_WriteShort(&sv.datagram, effectnum);
2838 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2839 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2840 MSG_WriteShort(&sv.datagram, count);
2843 SV_FlushBroadcastMessages();
2846 prvm_builtin_t vm_sv_builtins[] = {
2847 NULL, // #0 NULL function (not callable) (QUAKE)
2848 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
2849 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
2850 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
2851 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
2852 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
2853 VM_break, // #6 void() break (QUAKE)
2854 VM_random, // #7 float() random (QUAKE)
2855 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
2856 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
2857 VM_error, // #10 void(string e) error (QUAKE)
2858 VM_objerror, // #11 void(string e) objerror (QUAKE)
2859 VM_vlen, // #12 float(vector v) vlen (QUAKE)
2860 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
2861 VM_spawn, // #14 entity() spawn (QUAKE)
2862 VM_remove, // #15 void(entity e) remove (QUAKE)
2863 VM_SV_traceline, // #16 float(vector v1, vector v2, float tryents) traceline (QUAKE)
2864 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
2865 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
2866 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
2867 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
2868 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
2869 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
2870 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
2871 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
2872 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
2873 VM_ftos, // #26 string(float f) ftos (QUAKE)
2874 VM_vtos, // #27 string(vector v) vtos (QUAKE)
2875 VM_coredump, // #28 void() coredump (QUAKE)
2876 VM_traceon, // #29 void() traceon (QUAKE)
2877 VM_traceoff, // #30 void() traceoff (QUAKE)
2878 VM_eprint, // #31 void(entity e) eprint (QUAKE)
2879 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
2880 NULL, // #33 (QUAKE)
2881 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
2882 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
2883 VM_rint, // #36 float(float v) rint (QUAKE)
2884 VM_floor, // #37 float(float v) floor (QUAKE)
2885 VM_ceil, // #38 float(float v) ceil (QUAKE)
2886 NULL, // #39 (QUAKE)
2887 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
2888 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
2889 NULL, // #42 (QUAKE)
2890 VM_fabs, // #43 float(float f) fabs (QUAKE)
2891 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
2892 VM_cvar, // #45 float(string s) cvar (QUAKE)
2893 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
2894 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
2895 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
2896 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
2897 NULL, // #50 (QUAKE)
2898 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
2899 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
2900 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
2901 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
2902 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
2903 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
2904 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
2905 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
2906 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
2907 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
2908 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
2909 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
2910 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
2911 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
2912 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
2913 NULL, // #66 (QUAKE)
2914 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
2915 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
2916 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
2917 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
2918 NULL, // #71 (QUAKE)
2919 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
2920 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
2921 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
2922 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
2923 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
2924 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
2925 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
2926 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
2927 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
2928 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2929 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
2930 NULL, // #83 (QUAKE)
2931 NULL, // #84 (QUAKE)
2932 NULL, // #85 (QUAKE)
2933 NULL, // #86 (QUAKE)
2934 NULL, // #87 (QUAKE)
2935 NULL, // #88 (QUAKE)
2936 NULL, // #89 (QUAKE)
2937 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2938 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2939 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2940 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2941 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2942 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2943 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2944 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2945 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2946 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2947 // FrikaC and Telejano range #100-#199
2958 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2959 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2960 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2961 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2962 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2963 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
2964 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2965 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2966 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2967 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3048 // FTEQW range #200-#299
3067 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3070 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3071 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3072 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3073 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3074 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3075 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3076 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3077 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3078 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3079 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3081 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3149 // CSQC range #300-#399
3150 NULL, // #300 void() clearscene (EXT_CSQC)
3151 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3152 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3153 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3154 NULL, // #304 void() renderscene (EXT_CSQC)
3155 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3156 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3157 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3158 NULL, // #308 void() R_EndPolygon
3160 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3161 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3165 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3166 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3167 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3168 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3169 NULL, // #319 void(string name) freepic (EXT_CSQC)
3170 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3171 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3172 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3173 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3174 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3175 NULL, // #325 void(void) drawresetcliparea
3180 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3181 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3182 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3183 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3184 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3185 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3186 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3187 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3188 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3189 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3190 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3191 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3192 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3193 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3194 NULL, // #344 vector() getmousepos (EXT_CSQC)
3195 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3196 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3197 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3198 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3199 NULL, // #349 float() isdemo (EXT_CSQC)
3200 VM_isserver, // #350 float() isserver (EXT_CSQC)
3201 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3202 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3203 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3204 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3210 NULL, // #360 float() readbyte (EXT_CSQC)
3211 NULL, // #361 float() readchar (EXT_CSQC)
3212 NULL, // #362 float() readshort (EXT_CSQC)
3213 NULL, // #363 float() readlong (EXT_CSQC)
3214 NULL, // #364 float() readcoord (EXT_CSQC)
3215 NULL, // #365 float() readangle (EXT_CSQC)
3216 NULL, // #366 string() readstring (EXT_CSQC)
3217 NULL, // #367 float() readfloat (EXT_CSQC)
3250 // LordHavoc's range #400-#499
3251 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3252 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3253 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3254 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3255 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3256 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3257 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3258 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3259 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)
3260 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3261 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3262 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3263 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3264 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3265 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3266 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3267 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3268 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3269 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3270 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3271 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3272 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3273 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3274 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3275 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3276 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3277 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3278 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3279 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3280 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3281 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3282 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3283 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3284 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3285 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3286 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3287 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3288 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3289 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3290 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3291 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3292 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3293 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3294 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3295 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3296 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3297 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3298 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3299 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3300 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3301 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3302 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3303 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3304 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3305 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3306 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3307 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3308 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3310 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3311 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3312 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3313 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3314 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3315 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3316 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3317 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3318 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3319 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3320 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3322 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3323 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3324 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3325 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3326 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3327 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3328 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3329 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3330 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3331 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3332 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3333 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3334 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3335 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3336 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3337 VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3345 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3346 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3353 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3355 void VM_SV_Cmd_Init(void)
3360 void VM_SV_Cmd_Reset(void)
3362 if(prog->funcoffsets.SV_Shutdown)
3364 func_t s = prog->funcoffsets.SV_Shutdown;
3365 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3366 PRVM_ExecuteProgram(s,"SV_Shutdown() required");