6 //============================================================================
11 char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
36 "DP_ENT_CUSTOMCOLORMAP "
37 "DP_ENT_EXTERIORMODELTOCLIENT "
39 "DP_ENT_LOWPRECISION "
43 "DP_GFX_EXTERNALTEXTURES "
44 "DP_GFX_EXTERNALTEXTURES_PERMAP "
46 "DP_GFX_QUAKE3MODELTAGS "
50 "DP_HALFLIFE_MAP_CVAR "
56 "DP_MOVETYPEBOUNCEMISSILE "
59 "DP_QC_ASINACOSATANATAN2TAN "
64 "DP_QC_CVAR_DEFSTRING "
65 "DP_QC_CVAR_DESCRIPTION "
72 "DP_QC_FINDCHAINFLAGS "
73 "DP_QC_FINDCHAINFLOAT "
79 "DP_QC_GETSURFACEPOINTATTRIBUTE "
82 "DP_QC_MULTIPLETEMPSTRINGS "
83 "DP_QC_NUM_FOR_EDICT "
85 "DP_QC_SINCOSSQRTPOW "
87 "DP_QC_STRINGBUFFERS "
88 "DP_QC_STRINGBUFFERS_CVARLIST "
89 "DP_QC_STRINGCOLORFUNCTIONS "
90 "DP_QC_STRING_CASE_FUNCTIONS "
92 "DP_QC_TOKENIZEBYSEPARATOR "
93 "DP_QC_TOKENIZE_CONSOLE "
96 "DP_QC_TRACE_MOVETYPE_HITMODEL "
97 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
98 "DP_QC_UNLIMITEDTEMPSTRINGS "
101 "DP_QC_VECTOANGLES_WITH_ROLL "
102 "DP_QC_VECTORVECTORS "
109 "DP_SND_DIRECTIONLESSATTNNONE "
116 "DP_SV_CLIENTCOLORS "
119 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
120 "DP_SV_DRAWONLYTOCLIENT "
123 "DP_SV_ENTITYCONTENTSTRANSITION "
124 "DP_SV_MODELFLAGS_AS_EFFECTS "
125 "DP_SV_MOVETYPESTEP_LANDEVENT "
127 "DP_SV_NODRAWTOCLIENT "
128 "DP_SV_ONENTITYNOSPAWNFUNCTION "
129 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
131 "DP_SV_PLAYERPHYSICS "
132 "DP_SV_POINTPARTICLES "
134 "DP_SV_PRECACHEANYTIME "
138 "DP_SV_ROTATINGBMODEL "
142 "DP_SV_SPAWNFUNC_PREFIX "
143 "DP_SV_WRITEPICTURE "
144 "DP_SV_WRITEUNTERMINATEDSTRING "
148 "DP_TE_EXPLOSIONRGB "
150 "DP_TE_PARTICLECUBE "
151 "DP_TE_PARTICLERAIN "
152 "DP_TE_PARTICLESNOW "
154 "DP_TE_QUADEFFECTS1 "
157 "DP_TE_STANDARDEFFECTBUILTINS "
158 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
163 "KRIMZON_SV_PARSECLIENTCOMMAND "
166 "NEXUIZ_PLAYERMODEL "
168 "PRYDON_CLIENTCURSOR "
169 "TENEBRAE_GFX_DLIGHTS "
171 //"EXT_CSQC " // not ready yet
178 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.
180 setorigin (entity, origin)
183 static void VM_SV_setorigin (void)
188 VM_SAFEPARMCOUNT(2, VM_setorigin);
190 e = PRVM_G_EDICT(OFS_PARM0);
191 if (e == prog->edicts)
193 VM_Warning("setorigin: can not modify world entity\n");
196 if (e->priv.server->free)
198 VM_Warning("setorigin: can not modify free entity\n");
201 org = PRVM_G_VECTOR(OFS_PARM1);
202 VectorCopy (org, e->fields.server->origin);
203 SV_LinkEdict (e, false);
206 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
207 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
211 for (i=0 ; i<3 ; i++)
213 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
215 // set derived values
216 VectorCopy (min, e->fields.server->mins);
217 VectorCopy (max, e->fields.server->maxs);
218 VectorSubtract (max, min, e->fields.server->size);
220 SV_LinkEdict (e, false);
227 the size box is rotated by the current angle
228 LordHavoc: no it isn't...
230 setsize (entity, minvector, maxvector)
233 static void VM_SV_setsize (void)
238 VM_SAFEPARMCOUNT(3, VM_setsize);
240 e = PRVM_G_EDICT(OFS_PARM0);
241 if (e == prog->edicts)
243 VM_Warning("setsize: can not modify world entity\n");
246 if (e->priv.server->free)
248 VM_Warning("setsize: can not modify free entity\n");
251 min = PRVM_G_VECTOR(OFS_PARM1);
252 max = PRVM_G_VECTOR(OFS_PARM2);
253 SetMinMaxSize (e, min, max, false);
261 setmodel(entity, model)
264 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
265 static void VM_SV_setmodel (void)
271 VM_SAFEPARMCOUNT(2, VM_setmodel);
273 e = PRVM_G_EDICT(OFS_PARM0);
274 if (e == prog->edicts)
276 VM_Warning("setmodel: can not modify world entity\n");
279 if (e->priv.server->free)
281 VM_Warning("setmodel: can not modify free entity\n");
284 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
285 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
286 e->fields.server->modelindex = i;
292 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
293 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
295 SetMinMaxSize (e, quakemins, quakemaxs, true);
298 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
305 single print to a specific client
307 sprint(clientent, value)
310 static void VM_SV_sprint (void)
314 char string[VM_STRINGTEMP_LENGTH];
316 VM_VarString(1, string, sizeof(string));
318 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
320 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
321 // LordHavoc: div0 requested that sprintto world operate like print
328 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
330 VM_Warning("tried to centerprint to a non-client\n");
334 client = svs.clients + entnum-1;
335 if (!client->netconnection)
338 MSG_WriteChar(&client->netconnection->message,svc_print);
339 MSG_WriteString(&client->netconnection->message, string);
347 single print to a specific client
349 centerprint(clientent, value)
352 static void VM_SV_centerprint (void)
356 char string[VM_STRINGTEMP_LENGTH];
358 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
360 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
362 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
364 VM_Warning("tried to centerprint to a non-client\n");
368 client = svs.clients + entnum-1;
369 if (!client->netconnection)
372 VM_VarString(1, string, sizeof(string));
373 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
374 MSG_WriteString(&client->netconnection->message, string);
381 particle(origin, color, count)
384 static void VM_SV_particle (void)
390 VM_SAFEPARMCOUNT(4, VM_SV_particle);
392 org = PRVM_G_VECTOR(OFS_PARM0);
393 dir = PRVM_G_VECTOR(OFS_PARM1);
394 color = PRVM_G_FLOAT(OFS_PARM2);
395 count = PRVM_G_FLOAT(OFS_PARM3);
396 SV_StartParticle (org, dir, (int)color, (int)count);
406 static void VM_SV_ambientsound (void)
410 float vol, attenuation;
413 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
415 pos = PRVM_G_VECTOR (OFS_PARM0);
416 samp = PRVM_G_STRING(OFS_PARM1);
417 vol = PRVM_G_FLOAT(OFS_PARM2);
418 attenuation = PRVM_G_FLOAT(OFS_PARM3);
420 // check to see if samp was properly precached
421 soundnum = SV_SoundIndex(samp, 1);
429 // add an svc_spawnambient command to the level signon packet
432 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
434 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
436 MSG_WriteVector(&sv.signon, pos, sv.protocol);
438 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
439 MSG_WriteShort (&sv.signon, soundnum);
441 MSG_WriteByte (&sv.signon, soundnum);
443 MSG_WriteByte (&sv.signon, (int)(vol*255));
444 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
452 Each entity can have eight independant sound sources, like voice,
455 Channel 0 is an auto-allocate channel, the others override anything
456 already running on that entity/channel pair.
458 An attenuation of 0 will play full volume everywhere in the level.
459 Larger attenuations will drop off.
463 static void VM_SV_sound (void)
467 prvm_edict_t *entity;
471 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
473 entity = PRVM_G_EDICT(OFS_PARM0);
474 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
475 sample = PRVM_G_STRING(OFS_PARM2);
476 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
477 attenuation = PRVM_G_FLOAT(OFS_PARM4);
480 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
484 if (volume < 0 || volume > 255)
486 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
490 if (attenuation < 0 || attenuation > 4)
492 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
496 if (channel < 0 || channel > 7)
498 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
502 SV_StartSound (entity, channel, sample, volume, attenuation);
509 Follows the same logic as VM_SV_sound, except instead of
510 an entity, an origin for the sound is provided, and channel
511 is omitted (since no entity is being tracked).
515 static void VM_SV_pointsound(void)
522 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
524 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
525 sample = PRVM_G_STRING(OFS_PARM1);
526 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
527 attenuation = PRVM_G_FLOAT(OFS_PARM3);
529 if (volume < 0 || volume > 255)
531 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
535 if (attenuation < 0 || attenuation > 4)
537 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
541 SV_StartPointSound (org, sample, volume, attenuation);
548 Used for use tracing and shot targeting
549 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
550 if the tryents flag is set.
552 traceline (vector1, vector2, movetype, ignore)
555 static void VM_SV_traceline (void)
562 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
564 prog->xfunction->builtinsprofile += 30;
566 v1 = PRVM_G_VECTOR(OFS_PARM0);
567 v2 = PRVM_G_VECTOR(OFS_PARM1);
568 move = (int)PRVM_G_FLOAT(OFS_PARM2);
569 ent = PRVM_G_EDICT(OFS_PARM3);
571 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]))
572 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));
574 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
576 VM_SetTraceGlobals(&trace);
584 Used for use tracing and shot targeting
585 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
586 if the tryents flag is set.
588 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
591 // LordHavoc: added this for my own use, VERY useful, similar to traceline
592 static void VM_SV_tracebox (void)
594 float *v1, *v2, *m1, *m2;
599 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
601 prog->xfunction->builtinsprofile += 30;
603 v1 = PRVM_G_VECTOR(OFS_PARM0);
604 m1 = PRVM_G_VECTOR(OFS_PARM1);
605 m2 = PRVM_G_VECTOR(OFS_PARM2);
606 v2 = PRVM_G_VECTOR(OFS_PARM3);
607 move = (int)PRVM_G_FLOAT(OFS_PARM4);
608 ent = PRVM_G_EDICT(OFS_PARM5);
610 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]))
611 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));
613 trace = SV_Move (v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
615 VM_SetTraceGlobals(&trace);
618 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
623 vec3_t original_origin;
624 vec3_t original_velocity;
625 vec3_t original_angles;
626 vec3_t original_avelocity;
630 VectorCopy(tossent->fields.server->origin , original_origin );
631 VectorCopy(tossent->fields.server->velocity , original_velocity );
632 VectorCopy(tossent->fields.server->angles , original_angles );
633 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
635 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
636 if (val != NULL && val->_float != 0)
637 gravity = val->_float;
640 gravity *= sv_gravity.value * 0.025;
642 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
644 SV_CheckVelocity (tossent);
645 tossent->fields.server->velocity[2] -= gravity;
646 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
647 VectorScale (tossent->fields.server->velocity, 0.05, move);
648 VectorAdd (tossent->fields.server->origin, move, end);
649 trace = SV_Move (tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
650 VectorCopy (trace.endpos, tossent->fields.server->origin);
651 tossent->fields.server->velocity[2] -= gravity;
653 if (trace.fraction < 1)
657 VectorCopy(original_origin , tossent->fields.server->origin );
658 VectorCopy(original_velocity , tossent->fields.server->velocity );
659 VectorCopy(original_angles , tossent->fields.server->angles );
660 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
665 static void VM_SV_tracetoss (void)
669 prvm_edict_t *ignore;
671 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
673 prog->xfunction->builtinsprofile += 600;
675 ent = PRVM_G_EDICT(OFS_PARM0);
676 if (ent == prog->edicts)
678 VM_Warning("tracetoss: can not use world entity\n");
681 ignore = PRVM_G_EDICT(OFS_PARM1);
683 trace = SV_Trace_Toss (ent, ignore);
685 VM_SetTraceGlobals(&trace);
688 //============================================================================
690 static int checkpvsbytes;
691 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
693 static int VM_SV_newcheckclient (int check)
699 // cycle to the next one
701 check = bound(1, check, svs.maxclients);
702 if (check == svs.maxclients)
710 prog->xfunction->builtinsprofile++;
712 if (i == svs.maxclients+1)
714 // look up the client's edict
715 ent = PRVM_EDICT_NUM(i);
716 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
717 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
719 // found a valid client (possibly the same one again)
723 // get the PVS for the entity
724 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
726 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
727 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
736 Returns a client (or object that has a client enemy) that would be a
739 If there is more than one valid option, they are cycled each frame
741 If (self.origin + self.viewofs) is not in the PVS of the current target,
742 it is not returned at all.
747 int c_invis, c_notvis;
748 static void VM_SV_checkclient (void)
750 prvm_edict_t *ent, *self;
753 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
755 // find a new check if on a new frame
756 if (sv.time - sv.lastchecktime >= 0.1)
758 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
759 sv.lastchecktime = sv.time;
762 // return check if it might be visible
763 ent = PRVM_EDICT_NUM(sv.lastcheck);
764 if (ent->priv.server->free || ent->fields.server->health <= 0)
766 VM_RETURN_EDICT(prog->edicts);
770 // if current entity can't possibly see the check entity, return 0
771 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
772 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
773 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
776 VM_RETURN_EDICT(prog->edicts);
780 // might be able to see it
782 VM_RETURN_EDICT(ent);
785 //============================================================================
792 Sends text over to the client's execution buffer
794 stuffcmd (clientent, value, ...)
797 static void VM_SV_stuffcmd (void)
801 char string[VM_STRINGTEMP_LENGTH];
803 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
805 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
806 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
808 VM_Warning("Can't stuffcmd to a non-client\n");
812 VM_VarString(1, string, sizeof(string));
815 host_client = svs.clients + entnum-1;
816 Host_ClientCommands ("%s", string);
824 Returns a chain of entities that have origins within a spherical area
826 findradius (origin, radius)
829 static void VM_SV_findradius (void)
831 prvm_edict_t *ent, *chain;
832 vec_t radius, radius2;
833 vec3_t org, eorg, mins, maxs;
836 prvm_edict_t *touchedicts[MAX_EDICTS];
838 VM_SAFEPARMCOUNT(2, VM_SV_findradius);
840 chain = (prvm_edict_t *)prog->edicts;
842 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
843 radius = PRVM_G_FLOAT(OFS_PARM1);
844 radius2 = radius * radius;
846 mins[0] = org[0] - (radius + 1);
847 mins[1] = org[1] - (radius + 1);
848 mins[2] = org[2] - (radius + 1);
849 maxs[0] = org[0] + (radius + 1);
850 maxs[1] = org[1] + (radius + 1);
851 maxs[2] = org[2] + (radius + 1);
852 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
853 if (numtouchedicts > MAX_EDICTS)
855 // this never happens
856 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
857 numtouchedicts = MAX_EDICTS;
859 for (i = 0;i < numtouchedicts;i++)
861 ent = touchedicts[i];
862 prog->xfunction->builtinsprofile++;
863 // Quake did not return non-solid entities but darkplaces does
864 // (note: this is the reason you can't blow up fallen zombies)
865 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
867 // LordHavoc: compare against bounding box rather than center so it
868 // doesn't miss large objects, and use DotProduct instead of Length
869 // for a major speedup
870 VectorSubtract(org, ent->fields.server->origin, eorg);
871 if (sv_gameplayfix_findradiusdistancetobox.integer)
873 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
874 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
875 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
878 VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
879 if (DotProduct(eorg, eorg) < radius2)
881 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
886 VM_RETURN_EDICT(chain);
889 static void VM_SV_precache_sound (void)
891 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
892 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
895 static void VM_SV_precache_model (void)
897 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
898 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
899 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
906 float(float yaw, float dist[, settrace]) walkmove
909 static void VM_SV_walkmove (void)
918 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
920 // assume failure if it returns early
921 PRVM_G_FLOAT(OFS_RETURN) = 0;
923 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
924 if (ent == prog->edicts)
926 VM_Warning("walkmove: can not modify world entity\n");
929 if (ent->priv.server->free)
931 VM_Warning("walkmove: can not modify free entity\n");
934 yaw = PRVM_G_FLOAT(OFS_PARM0);
935 dist = PRVM_G_FLOAT(OFS_PARM1);
936 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
938 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
941 yaw = yaw*M_PI*2 / 360;
943 move[0] = cos(yaw)*dist;
944 move[1] = sin(yaw)*dist;
947 // save program state, because SV_movestep may call other progs
948 oldf = prog->xfunction;
949 oldself = prog->globals.server->self;
951 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
954 // restore program state
955 prog->xfunction = oldf;
956 prog->globals.server->self = oldself;
966 static void VM_SV_droptofloor (void)
972 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
974 // assume failure if it returns early
975 PRVM_G_FLOAT(OFS_RETURN) = 0;
977 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
978 if (ent == prog->edicts)
980 VM_Warning("droptofloor: can not modify world entity\n");
983 if (ent->priv.server->free)
985 VM_Warning("droptofloor: can not modify free entity\n");
989 VectorCopy (ent->fields.server->origin, end);
992 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
993 SV_UnstickEntity(ent);
995 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
996 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
999 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]);
1000 VectorAdd(ent->fields.server->origin, offset, org);
1001 trace = SV_Move (org, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1002 VectorSubtract(trace.endpos, offset, trace.endpos);
1003 if (trace.startsolid)
1005 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]);
1006 SV_UnstickEntity(ent);
1007 SV_LinkEdict (ent, false);
1008 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1009 ent->fields.server->groundentity = 0;
1010 PRVM_G_FLOAT(OFS_RETURN) = 1;
1012 else if (trace.fraction < 1)
1014 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]);
1015 VectorCopy (trace.endpos, ent->fields.server->origin);
1016 SV_UnstickEntity(ent);
1017 SV_LinkEdict (ent, false);
1018 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1019 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1020 PRVM_G_FLOAT(OFS_RETURN) = 1;
1021 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1022 ent->priv.server->suspendedinairflag = true;
1027 if (trace.fraction != 1)
1029 if (trace.fraction < 1)
1030 VectorCopy (trace.endpos, ent->fields.server->origin);
1031 SV_LinkEdict (ent, false);
1032 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1033 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1034 PRVM_G_FLOAT(OFS_RETURN) = 1;
1035 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1036 ent->priv.server->suspendedinairflag = true;
1045 void(float style, string value) lightstyle
1048 static void VM_SV_lightstyle (void)
1055 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1057 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1058 val = PRVM_G_STRING(OFS_PARM1);
1060 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1061 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1064 // change the string in sv
1065 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1067 // send message to all clients on this server
1068 if (sv.state != ss_active)
1071 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1073 if (client->active && client->netconnection)
1075 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1076 MSG_WriteChar (&client->netconnection->message,style);
1077 MSG_WriteString (&client->netconnection->message, val);
1087 static void VM_SV_checkbottom (void)
1089 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1090 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1098 static void VM_SV_pointcontents (void)
1100 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1101 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1108 Pick a vector for the player to shoot along
1109 vector aim(entity, missilespeed)
1112 static void VM_SV_aim (void)
1114 prvm_edict_t *ent, *check, *bestent;
1115 vec3_t start, dir, end, bestdir;
1118 float dist, bestdist;
1121 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1123 // assume failure if it returns early
1124 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1125 // if sv_aim is so high it can't possibly accept anything, skip out early
1126 if (sv_aim.value >= 1)
1129 ent = PRVM_G_EDICT(OFS_PARM0);
1130 if (ent == prog->edicts)
1132 VM_Warning("aim: can not use world entity\n");
1135 if (ent->priv.server->free)
1137 VM_Warning("aim: can not use free entity\n");
1140 speed = PRVM_G_FLOAT(OFS_PARM1);
1142 VectorCopy (ent->fields.server->origin, start);
1145 // try sending a trace straight
1146 VectorCopy (prog->globals.server->v_forward, dir);
1147 VectorMA (start, 2048, dir, end);
1148 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1149 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1150 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1152 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1157 // try all possible entities
1158 VectorCopy (dir, bestdir);
1159 bestdist = sv_aim.value;
1162 check = PRVM_NEXT_EDICT(prog->edicts);
1163 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1165 prog->xfunction->builtinsprofile++;
1166 if (check->fields.server->takedamage != DAMAGE_AIM)
1170 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1171 continue; // don't aim at teammate
1172 for (j=0 ; j<3 ; j++)
1173 end[j] = check->fields.server->origin[j]
1174 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1175 VectorSubtract (end, start, dir);
1176 VectorNormalize (dir);
1177 dist = DotProduct (dir, prog->globals.server->v_forward);
1178 if (dist < bestdist)
1179 continue; // to far to turn
1180 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1181 if (tr.ent == check)
1182 { // can shoot at this one
1190 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1191 dist = DotProduct (dir, prog->globals.server->v_forward);
1192 VectorScale (prog->globals.server->v_forward, dist, end);
1194 VectorNormalize (end);
1195 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1199 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1204 ===============================================================================
1208 ===============================================================================
1211 #define MSG_BROADCAST 0 // unreliable to all
1212 #define MSG_ONE 1 // reliable to one (msg_entity)
1213 #define MSG_ALL 2 // reliable to all
1214 #define MSG_INIT 3 // write to the init string
1215 #define MSG_ENTITY 5
1217 sizebuf_t *WriteDest (void)
1223 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1227 return &sv.datagram;
1230 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1231 entnum = PRVM_NUM_FOR_EDICT(ent);
1232 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1234 VM_Warning ("WriteDest: tried to write to non-client\n");
1235 return &sv.reliable_datagram;
1238 return &svs.clients[entnum-1].netconnection->message;
1241 VM_Warning ("WriteDest: bad destination\n");
1243 return &sv.reliable_datagram;
1249 return sv.writeentitiestoclient_msg;
1255 static void VM_SV_WriteByte (void)
1257 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1258 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1261 static void VM_SV_WriteChar (void)
1263 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1264 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1267 static void VM_SV_WriteShort (void)
1269 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1270 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1273 static void VM_SV_WriteLong (void)
1275 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1276 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1279 static void VM_SV_WriteAngle (void)
1281 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1282 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1285 static void VM_SV_WriteCoord (void)
1287 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1288 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1291 static void VM_SV_WriteString (void)
1293 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1294 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1297 static void VM_SV_WriteUnterminatedString (void)
1299 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1300 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1304 static void VM_SV_WriteEntity (void)
1306 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1307 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1310 // writes a picture as at most size bytes of data
1312 // IMGNAME \0 SIZE(short) IMGDATA
1313 // if failed to read/compress:
1315 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1316 static void VM_SV_WritePicture (void)
1318 const char *imgname;
1322 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1324 imgname = PRVM_G_STRING(OFS_PARM1);
1325 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1329 MSG_WriteString(WriteDest(), imgname);
1330 if(Image_Compress(imgname, size, &buf, &size))
1333 MSG_WriteShort(WriteDest(), size);
1334 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1339 MSG_WriteShort(WriteDest(), 0);
1343 //////////////////////////////////////////////////////////
1345 static void VM_SV_makestatic (void)
1350 // allow 0 parameters due to an id1 qc bug in which this function is used
1351 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1352 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1354 if (prog->argc >= 1)
1355 ent = PRVM_G_EDICT(OFS_PARM0);
1357 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1358 if (ent == prog->edicts)
1360 VM_Warning("makestatic: can not modify world entity\n");
1363 if (ent->priv.server->free)
1365 VM_Warning("makestatic: can not modify free entity\n");
1370 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1375 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1376 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1377 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1379 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1381 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1382 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1383 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1387 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1388 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1389 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1392 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1393 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1394 for (i=0 ; i<3 ; i++)
1396 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1397 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1400 // throw the entity away now
1404 //=============================================================================
1411 static void VM_SV_setspawnparms (void)
1417 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1419 ent = PRVM_G_EDICT(OFS_PARM0);
1420 i = PRVM_NUM_FOR_EDICT(ent);
1421 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1423 Con_Print("tried to setspawnparms on a non-client\n");
1427 // copy spawn parms out of the client_t
1428 client = svs.clients + i-1;
1429 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1430 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1437 Returns a color vector indicating the lighting at the requested point.
1439 (Internal Operation note: actually measures the light beneath the point, just like
1440 the model lighting on the client)
1445 static void VM_SV_getlight (void)
1447 vec3_t ambientcolor, diffusecolor, diffusenormal;
1449 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1450 p = PRVM_G_VECTOR(OFS_PARM0);
1451 VectorClear(ambientcolor);
1452 VectorClear(diffusecolor);
1453 VectorClear(diffusenormal);
1454 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1455 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1456 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1461 unsigned char type; // 1/2/8 or other value if isn't used
1465 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1466 static int vm_customstats_last;
1468 void VM_CustomStats_Clear (void)
1472 Z_Free(vm_customstats);
1473 vm_customstats = NULL;
1474 vm_customstats_last = -1;
1478 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1486 for(i=0; i<vm_customstats_last+1 ;i++)
1488 if(!vm_customstats[i].type)
1490 switch(vm_customstats[i].type)
1492 //string as 16 bytes
1495 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1496 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1497 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1498 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1499 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1501 //float field sent as-is
1503 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1505 //integer value of float field
1507 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1515 // void(float index, float type, .void field) SV_AddStat = #232;
1516 // Set up an auto-sent player stat.
1517 // Client's get thier own fields sent to them. Index may not be less than 32.
1518 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1519 // 1: string (4 stats carrying a total of 16 charactures)
1520 // 2: float (one stat, float converted to an integer for transportation)
1521 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1522 static void VM_SV_AddStat (void)
1527 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1531 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1534 VM_Warning("PF_SV_AddStat: not enough memory\n");
1538 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1539 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1540 off = PRVM_G_INT (OFS_PARM2);
1545 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1548 if(i >= (MAX_CL_STATS-32))
1550 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1553 if(i > (MAX_CL_STATS-32-4) && type == 1)
1555 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1558 vm_customstats[i].type = type;
1559 vm_customstats[i].fieldoffset = off;
1560 if(vm_customstats_last < i)
1561 vm_customstats_last = i;
1568 copies data from one entity to another
1570 copyentity(src, dst)
1573 static void VM_SV_copyentity (void)
1575 prvm_edict_t *in, *out;
1576 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1577 in = PRVM_G_EDICT(OFS_PARM0);
1578 if (in == prog->edicts)
1580 VM_Warning("copyentity: can not read world entity\n");
1583 if (in->priv.server->free)
1585 VM_Warning("copyentity: can not read free entity\n");
1588 out = PRVM_G_EDICT(OFS_PARM1);
1589 if (out == prog->edicts)
1591 VM_Warning("copyentity: can not modify world entity\n");
1594 if (out->priv.server->free)
1596 VM_Warning("copyentity: can not modify free entity\n");
1599 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1600 SV_LinkEdict(out, false);
1608 sets the color of a client and broadcasts the update to all connected clients
1610 setcolor(clientent, value)
1613 static void VM_SV_setcolor (void)
1619 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1620 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1621 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1623 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1625 Con_Print("tried to setcolor a non-client\n");
1629 client = svs.clients + entnum-1;
1632 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1634 client->edict->fields.server->team = (i & 15) + 1;
1637 if (client->old_colors != client->colors)
1639 client->old_colors = client->colors;
1640 // send notification to all clients
1641 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1642 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1643 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1651 effect(origin, modelname, startframe, framecount, framerate)
1654 static void VM_SV_effect (void)
1658 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1659 s = PRVM_G_STRING(OFS_PARM1);
1662 VM_Warning("effect: no model specified\n");
1666 i = SV_ModelIndex(s, 1);
1669 VM_Warning("effect: model not precached\n");
1673 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1675 VM_Warning("effect: framecount < 1\n");
1679 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1681 VM_Warning("effect: framerate < 1\n");
1685 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));
1688 static void VM_SV_te_blood (void)
1690 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1691 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1693 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1694 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1696 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1697 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1698 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1700 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1701 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1702 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1704 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1705 SV_FlushBroadcastMessages();
1708 static void VM_SV_te_bloodshower (void)
1710 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1711 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1713 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1714 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1716 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1717 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1718 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1720 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1721 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1722 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1724 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1726 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1727 SV_FlushBroadcastMessages();
1730 static void VM_SV_te_explosionrgb (void)
1732 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1733 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1734 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1736 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1737 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1738 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1740 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1741 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1742 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1743 SV_FlushBroadcastMessages();
1746 static void VM_SV_te_particlecube (void)
1748 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1749 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1751 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1752 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1754 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1755 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1756 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1758 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1759 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1760 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1762 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1763 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1764 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1766 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1768 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1769 // gravity true/false
1770 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1772 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1773 SV_FlushBroadcastMessages();
1776 static void VM_SV_te_particlerain (void)
1778 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1779 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1781 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1782 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1784 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1785 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1786 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1788 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1789 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1790 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1792 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1793 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1794 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1796 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1798 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1799 SV_FlushBroadcastMessages();
1802 static void VM_SV_te_particlesnow (void)
1804 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1805 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1807 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1808 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1810 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1812 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1814 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1815 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1816 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1818 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1819 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1820 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1822 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1824 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1825 SV_FlushBroadcastMessages();
1828 static void VM_SV_te_spark (void)
1830 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1831 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1833 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1834 MSG_WriteByte(&sv.datagram, TE_SPARK);
1836 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1837 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1838 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1840 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1841 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1842 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1844 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1845 SV_FlushBroadcastMessages();
1848 static void VM_SV_te_gunshotquad (void)
1850 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1851 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1852 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1854 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1855 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1856 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1857 SV_FlushBroadcastMessages();
1860 static void VM_SV_te_spikequad (void)
1862 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1863 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1864 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1866 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1868 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1869 SV_FlushBroadcastMessages();
1872 static void VM_SV_te_superspikequad (void)
1874 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1875 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1876 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1878 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1879 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1880 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1881 SV_FlushBroadcastMessages();
1884 static void VM_SV_te_explosionquad (void)
1886 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
1887 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1888 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1890 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1891 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1892 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1893 SV_FlushBroadcastMessages();
1896 static void VM_SV_te_smallflash (void)
1898 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
1899 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1900 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1905 SV_FlushBroadcastMessages();
1908 static void VM_SV_te_customflash (void)
1910 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
1911 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1913 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1914 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1916 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1917 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1918 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1920 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1922 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1924 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1925 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1926 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1927 SV_FlushBroadcastMessages();
1930 static void VM_SV_te_gunshot (void)
1932 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
1933 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1934 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1936 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1939 SV_FlushBroadcastMessages();
1942 static void VM_SV_te_spike (void)
1944 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
1945 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1946 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1948 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1949 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1950 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1951 SV_FlushBroadcastMessages();
1954 static void VM_SV_te_superspike (void)
1956 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
1957 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1958 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1963 SV_FlushBroadcastMessages();
1966 static void VM_SV_te_explosion (void)
1968 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
1969 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1970 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1972 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1973 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1974 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1975 SV_FlushBroadcastMessages();
1978 static void VM_SV_te_tarexplosion (void)
1980 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
1981 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1982 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1984 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1985 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1987 SV_FlushBroadcastMessages();
1990 static void VM_SV_te_wizspike (void)
1992 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
1993 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1994 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1996 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1997 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1998 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1999 SV_FlushBroadcastMessages();
2002 static void VM_SV_te_knightspike (void)
2004 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2005 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2006 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2008 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2009 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2010 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2011 SV_FlushBroadcastMessages();
2014 static void VM_SV_te_lavasplash (void)
2016 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2017 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2018 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2020 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2021 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2022 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2023 SV_FlushBroadcastMessages();
2026 static void VM_SV_te_teleport (void)
2028 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2029 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2030 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2032 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2033 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2034 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2035 SV_FlushBroadcastMessages();
2038 static void VM_SV_te_explosion2 (void)
2040 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2041 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2042 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2044 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2045 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2046 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2048 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2049 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2050 SV_FlushBroadcastMessages();
2053 static void VM_SV_te_lightning1 (void)
2055 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2056 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2057 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2059 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2061 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2062 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2063 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2065 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2066 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2067 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2068 SV_FlushBroadcastMessages();
2071 static void VM_SV_te_lightning2 (void)
2073 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2074 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2075 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2077 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2079 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2080 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2081 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2083 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2084 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2085 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2086 SV_FlushBroadcastMessages();
2089 static void VM_SV_te_lightning3 (void)
2091 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2092 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2093 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2095 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2097 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2098 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2099 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2101 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2102 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2103 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2104 SV_FlushBroadcastMessages();
2107 static void VM_SV_te_beam (void)
2109 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2110 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2111 MSG_WriteByte(&sv.datagram, TE_BEAM);
2113 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2115 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2116 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2117 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2119 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2120 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2121 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2122 SV_FlushBroadcastMessages();
2125 static void VM_SV_te_plasmaburn (void)
2127 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2128 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2129 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2130 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2131 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2132 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2133 SV_FlushBroadcastMessages();
2136 static void VM_SV_te_flamejet (void)
2138 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2139 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2140 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2142 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2143 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2144 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2146 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2147 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2148 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2150 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2151 SV_FlushBroadcastMessages();
2154 void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2157 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2159 bestdist = 1000000000;
2161 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2163 // clip original point to each triangle of the surface and find the
2164 // triangle that is closest
2165 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2166 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2167 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2168 TriangleNormal(v[0], v[1], v[2], facenormal);
2169 VectorNormalize(facenormal);
2170 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2171 VectorMA(p, offsetdist, facenormal, temp);
2172 for (j = 0, k = 2;j < 3;k = j, j++)
2174 VectorSubtract(v[k], v[j], edgenormal);
2175 CrossProduct(edgenormal, facenormal, sidenormal);
2176 VectorNormalize(sidenormal);
2177 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2179 VectorMA(temp, offsetdist, sidenormal, temp);
2181 dist = VectorDistance2(temp, p);
2182 if (bestdist > dist)
2185 VectorCopy(temp, out);
2190 static dp_model_t *getmodel(prvm_edict_t *ed)
2193 if (!ed || ed->priv.server->free)
2195 modelindex = (int)ed->fields.server->modelindex;
2196 if (modelindex < 1 || modelindex >= MAX_MODELS)
2198 return sv.models[modelindex];
2201 static msurface_t *getsurface(dp_model_t *model, int surfacenum)
2203 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2205 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2209 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2210 static void VM_SV_getsurfacenumpoints(void)
2213 msurface_t *surface;
2214 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints);
2215 // return 0 if no such surface
2216 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2218 PRVM_G_FLOAT(OFS_RETURN) = 0;
2222 // note: this (incorrectly) assumes it is a simple polygon
2223 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2225 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2226 static void VM_SV_getsurfacepoint(void)
2230 msurface_t *surface;
2232 VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint);
2233 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2234 ed = PRVM_G_EDICT(OFS_PARM0);
2235 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2237 // note: this (incorrectly) assumes it is a simple polygon
2238 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2239 if (pointnum < 0 || pointnum >= surface->num_vertices)
2241 // FIXME: implement rotation/scaling
2242 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2244 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
2245 // float SPA_POSITION = 0;
2246 // float SPA_S_AXIS = 1;
2247 // float SPA_T_AXIS = 2;
2248 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2249 // float SPA_TEXCOORDS0 = 4;
2250 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2251 // float SPA_LIGHTMAP0_COLOR = 6;
2252 static void VM_SV_getsurfacepointattribute(void)
2256 msurface_t *surface;
2260 VM_SAFEPARMCOUNT(4, VM_SV_getsurfacepoint);
2261 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2262 ed = PRVM_G_EDICT(OFS_PARM0);
2263 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2265 // note: this (incorrectly) assumes it is a simple polygon
2266 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2267 if (pointnum < 0 || pointnum >= surface->num_vertices)
2269 // FIXME: implement rotation/scaling
2270 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
2272 switch( attributetype ) {
2273 // float SPA_POSITION = 0;
2275 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2277 // float SPA_S_AXIS = 1;
2279 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2281 // float SPA_T_AXIS = 2;
2283 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2285 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2287 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2289 // float SPA_TEXCOORDS0 = 4;
2291 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2292 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
2293 ret[0] = texcoord[0];
2294 ret[1] = texcoord[1];
2298 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2300 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2301 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
2302 ret[0] = texcoord[0];
2303 ret[1] = texcoord[1];
2307 // float SPA_LIGHTMAP0_COLOR = 6;
2309 // ignore alpha for now..
2310 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2313 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2317 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2318 static void VM_SV_getsurfacenormal(void)
2321 msurface_t *surface;
2323 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal);
2324 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2325 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2327 // FIXME: implement rotation/scaling
2328 // note: this (incorrectly) assumes it is a simple polygon
2329 // note: this only returns the first triangle, so it doesn't work very
2330 // well for curved surfaces or arbitrary meshes
2331 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);
2332 VectorNormalize(normal);
2333 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2335 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2336 static void VM_SV_getsurfacetexture(void)
2339 msurface_t *surface;
2340 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture);
2341 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2342 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2344 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2346 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2347 static void VM_SV_getsurfacenearpoint(void)
2349 int surfacenum, best;
2351 vec_t dist, bestdist;
2354 msurface_t *surface;
2356 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint);
2357 PRVM_G_FLOAT(OFS_RETURN) = -1;
2358 ed = PRVM_G_EDICT(OFS_PARM0);
2359 point = PRVM_G_VECTOR(OFS_PARM1);
2361 if (!ed || ed->priv.server->free)
2363 model = getmodel(ed);
2364 if (!model || !model->num_surfaces)
2367 // FIXME: implement rotation/scaling
2368 VectorSubtract(point, ed->fields.server->origin, p);
2370 bestdist = 1000000000;
2371 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2373 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2374 // first see if the nearest point on the surface's box is closer than the previous match
2375 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2376 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2377 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2378 dist = VectorLength2(clipped);
2379 if (dist < bestdist)
2381 // it is, check the nearest point on the actual geometry
2382 clippointtosurface(model, surface, p, clipped);
2383 VectorSubtract(clipped, p, clipped);
2384 dist += VectorLength2(clipped);
2385 if (dist < bestdist)
2387 // that's closer too, store it as the best match
2393 PRVM_G_FLOAT(OFS_RETURN) = best;
2395 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2396 static void VM_SV_getsurfaceclippedpoint(void)
2400 msurface_t *surface;
2402 VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint);
2403 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2404 ed = PRVM_G_EDICT(OFS_PARM0);
2405 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2407 // FIXME: implement rotation/scaling
2408 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2409 clippointtosurface(model, surface, p, out);
2410 // FIXME: implement rotation/scaling
2411 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2414 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2415 //this function originally written by KrimZon, made shorter by LordHavoc
2416 static void VM_SV_clientcommand (void)
2418 client_t *temp_client;
2420 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2422 //find client for this entity
2423 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2424 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2426 Con_Print("PF_clientcommand: entity is not a client\n");
2430 temp_client = host_client;
2431 host_client = svs.clients + i;
2432 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2433 host_client = temp_client;
2436 //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)
2437 static void VM_SV_setattachment (void)
2439 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2440 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2441 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2445 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2447 if (e == prog->edicts)
2449 VM_Warning("setattachment: can not modify world entity\n");
2452 if (e->priv.server->free)
2454 VM_Warning("setattachment: can not modify free entity\n");
2458 if (tagentity == NULL)
2459 tagentity = prog->edicts;
2461 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2463 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2465 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2468 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2470 modelindex = (int)tagentity->fields.server->modelindex;
2471 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2473 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2475 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);
2478 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));
2482 /////////////////////////////////////////
2483 // DP_MD3_TAGINFO extension coded by VorteX
2485 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2490 i = (int)e->fields.server->modelindex;
2491 if (i < 1 || i >= MAX_MODELS)
2493 model = sv.models[i];
2495 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2498 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2500 float scale = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale)->_float;
2504 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);
2506 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);
2509 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2515 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2516 && (model = sv.models[(int)ent->fields.server->modelindex])
2517 && model->animscenes)
2519 // if model has wrong frame, engine automatically switches to model first frame
2520 frame = (int)ent->fields.server->frame;
2521 if (frame < 0 || frame >= model->numframes)
2523 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2525 *out = identitymatrix;
2529 // Warnings/errors code:
2530 // 0 - normal (everything all-right)
2533 // 3 - null or non-precached model
2534 // 4 - no tags with requested index
2535 // 5 - runaway loop at attachment chain
2536 extern cvar_t cl_bob;
2537 extern cvar_t cl_bobcycle;
2538 extern cvar_t cl_bobup;
2539 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2543 int modelindex, attachloop;
2544 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2547 *out = identitymatrix; // warnings and errors return identical matrix
2549 if (ent == prog->edicts)
2551 if (ent->priv.server->free)
2554 modelindex = (int)ent->fields.server->modelindex;
2555 if (modelindex <= 0 || modelindex > MAX_MODELS)
2558 model = sv.models[modelindex];
2560 tagmatrix = identitymatrix;
2561 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2565 if (attachloop >= 256) // prevent runaway looping
2567 // apply transformation by child's tagindex on parent entity and then
2568 // by parent entity itself
2569 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2570 if (ret && attachloop == 0)
2572 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2573 SV_GetEntityMatrix(ent, &entitymatrix, false);
2574 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2575 // next iteration we process the parent entity
2576 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2578 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2579 ent = PRVM_EDICT_NUM(val->edict);
2586 // RENDER_VIEWMODEL magic
2587 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2589 Matrix4x4_Copy(&tagmatrix, out);
2590 ent = PRVM_EDICT_NUM(val->edict);
2592 SV_GetEntityMatrix(ent, &entitymatrix, true);
2593 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2596 // Cl_bob, ported from rendering code
2597 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2600 // LordHavoc: this code is *weird*, but not replacable (I think it
2601 // should be done in QC on the server, but oh well, quake is quake)
2602 // LordHavoc: figured out bobup: the time at which the sin is at 180
2603 // degrees (which allows lengthening or squishing the peak or valley)
2604 cycle = sv.time/cl_bobcycle.value;
2605 cycle -= (int)cycle;
2606 if (cycle < cl_bobup.value)
2607 cycle = sin(M_PI * cycle / cl_bobup.value);
2609 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2610 // bob is proportional to velocity in the xy plane
2611 // (don't count Z, or jumping messes it up)
2612 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;
2613 bob = bob*0.3 + bob*0.7*cycle;
2614 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2621 //float(entity ent, string tagname) gettagindex;
2623 static void VM_SV_gettagindex (void)
2626 const char *tag_name;
2627 int modelindex, tag_index;
2629 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2631 ent = PRVM_G_EDICT(OFS_PARM0);
2632 tag_name = PRVM_G_STRING(OFS_PARM1);
2634 if (ent == prog->edicts)
2636 VM_Warning("gettagindex: can't affect world entity\n");
2639 if (ent->priv.server->free)
2641 VM_Warning("gettagindex: can't affect free entity\n");
2645 modelindex = (int)ent->fields.server->modelindex;
2647 if (modelindex <= 0 || modelindex > MAX_MODELS)
2648 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2651 tag_index = SV_GetTagIndex(ent, tag_name);
2653 if(developer.integer >= 100)
2654 Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2656 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2659 //vector(entity ent, float tagindex) gettaginfo;
2660 static void VM_SV_gettaginfo (void)
2664 matrix4x4_t tag_matrix;
2667 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2669 e = PRVM_G_EDICT(OFS_PARM0);
2670 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2672 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2673 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2678 VM_Warning("gettagindex: can't affect world entity\n");
2681 VM_Warning("gettagindex: can't affect free entity\n");
2684 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2687 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2690 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2695 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2696 static void VM_SV_dropclient (void)
2699 client_t *oldhostclient;
2700 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2701 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2702 if (clientnum < 0 || clientnum >= svs.maxclients)
2704 VM_Warning("dropclient: not a client\n");
2707 if (!svs.clients[clientnum].active)
2709 VM_Warning("dropclient: that client slot is not connected\n");
2712 oldhostclient = host_client;
2713 host_client = svs.clients + clientnum;
2714 SV_DropClient(false);
2715 host_client = oldhostclient;
2718 //entity() spawnclient (DP_SV_BOTCLIENT)
2719 static void VM_SV_spawnclient (void)
2723 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2724 prog->xfunction->builtinsprofile += 2;
2726 for (i = 0;i < svs.maxclients;i++)
2728 if (!svs.clients[i].active)
2730 prog->xfunction->builtinsprofile += 100;
2731 SV_ConnectClient (i, NULL);
2732 // this has to be set or else ClientDisconnect won't be called
2733 // we assume the qc will call ClientConnect...
2734 svs.clients[i].clientconnectcalled = true;
2735 ed = PRVM_EDICT_NUM(i + 1);
2739 VM_RETURN_EDICT(ed);
2742 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2743 static void VM_SV_clienttype (void)
2746 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2747 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2748 if (clientnum < 0 || clientnum >= svs.maxclients)
2749 PRVM_G_FLOAT(OFS_RETURN) = 3;
2750 else if (!svs.clients[clientnum].active)
2751 PRVM_G_FLOAT(OFS_RETURN) = 0;
2752 else if (svs.clients[clientnum].netconnection)
2753 PRVM_G_FLOAT(OFS_RETURN) = 1;
2755 PRVM_G_FLOAT(OFS_RETURN) = 2;
2762 string(string key) serverkey
2765 void VM_SV_serverkey(void)
2767 char string[VM_STRINGTEMP_LENGTH];
2768 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2769 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2770 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2773 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2774 static void VM_SV_setmodelindex (void)
2779 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2781 e = PRVM_G_EDICT(OFS_PARM0);
2782 if (e == prog->edicts)
2784 VM_Warning("setmodelindex: can not modify world entity\n");
2787 if (e->priv.server->free)
2789 VM_Warning("setmodelindex: can not modify free entity\n");
2792 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2793 if (i <= 0 || i > MAX_MODELS)
2795 VM_Warning("setmodelindex: invalid modelindex\n");
2798 if (!sv.model_precache[i][0])
2800 VM_Warning("setmodelindex: model not precached\n");
2804 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2805 e->fields.server->modelindex = i;
2811 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2812 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2814 SetMinMaxSize (e, quakemins, quakemaxs, true);
2817 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2820 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2821 static void VM_SV_modelnameforindex (void)
2824 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2826 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2828 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2829 if (i <= 0 || i > MAX_MODELS)
2831 VM_Warning("modelnameforindex: invalid modelindex\n");
2834 if (!sv.model_precache[i][0])
2836 VM_Warning("modelnameforindex: model not precached\n");
2840 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2843 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2844 static void VM_SV_particleeffectnum (void)
2847 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2848 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2851 PRVM_G_FLOAT(OFS_RETURN) = i;
2854 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2855 static void VM_SV_trailparticles (void)
2857 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2859 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2862 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2863 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2864 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2865 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2866 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2867 SV_FlushBroadcastMessages();
2870 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2871 static void VM_SV_pointparticles (void)
2873 int effectnum, count;
2875 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2877 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2880 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2881 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2882 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2883 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2884 if (count == 1 && !VectorLength2(vel))
2887 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2888 MSG_WriteShort(&sv.datagram, effectnum);
2889 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2893 // 1+2+12+12+2=29 bytes
2894 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2895 MSG_WriteShort(&sv.datagram, effectnum);
2896 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2897 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2898 MSG_WriteShort(&sv.datagram, count);
2901 SV_FlushBroadcastMessages();
2904 prvm_builtin_t vm_sv_builtins[] = {
2905 NULL, // #0 NULL function (not callable) (QUAKE)
2906 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
2907 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
2908 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
2909 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
2910 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
2911 VM_break, // #6 void() break (QUAKE)
2912 VM_random, // #7 float() random (QUAKE)
2913 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
2914 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
2915 VM_error, // #10 void(string e) error (QUAKE)
2916 VM_objerror, // #11 void(string e) objerror (QUAKE)
2917 VM_vlen, // #12 float(vector v) vlen (QUAKE)
2918 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
2919 VM_spawn, // #14 entity() spawn (QUAKE)
2920 VM_remove, // #15 void(entity e) remove (QUAKE)
2921 VM_SV_traceline, // #16 float(vector v1, vector v2, float tryents) traceline (QUAKE)
2922 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
2923 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
2924 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
2925 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
2926 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
2927 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
2928 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
2929 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
2930 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
2931 VM_ftos, // #26 string(float f) ftos (QUAKE)
2932 VM_vtos, // #27 string(vector v) vtos (QUAKE)
2933 VM_coredump, // #28 void() coredump (QUAKE)
2934 VM_traceon, // #29 void() traceon (QUAKE)
2935 VM_traceoff, // #30 void() traceoff (QUAKE)
2936 VM_eprint, // #31 void(entity e) eprint (QUAKE)
2937 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
2938 NULL, // #33 (QUAKE)
2939 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
2940 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
2941 VM_rint, // #36 float(float v) rint (QUAKE)
2942 VM_floor, // #37 float(float v) floor (QUAKE)
2943 VM_ceil, // #38 float(float v) ceil (QUAKE)
2944 NULL, // #39 (QUAKE)
2945 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
2946 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
2947 NULL, // #42 (QUAKE)
2948 VM_fabs, // #43 float(float f) fabs (QUAKE)
2949 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
2950 VM_cvar, // #45 float(string s) cvar (QUAKE)
2951 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
2952 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
2953 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
2954 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
2955 NULL, // #50 (QUAKE)
2956 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
2957 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
2958 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
2959 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
2960 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
2961 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
2962 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
2963 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
2964 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
2965 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
2966 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
2967 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
2968 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
2969 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
2970 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
2971 NULL, // #66 (QUAKE)
2972 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
2973 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
2974 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
2975 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
2976 NULL, // #71 (QUAKE)
2977 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
2978 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
2979 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
2980 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
2981 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
2982 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
2983 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
2984 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
2985 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
2986 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2987 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
2988 NULL, // #83 (QUAKE)
2989 NULL, // #84 (QUAKE)
2990 NULL, // #85 (QUAKE)
2991 NULL, // #86 (QUAKE)
2992 NULL, // #87 (QUAKE)
2993 NULL, // #88 (QUAKE)
2994 NULL, // #89 (QUAKE)
2995 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2996 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2997 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2998 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2999 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3000 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3001 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3002 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3003 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3004 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3005 // FrikaC and Telejano range #100-#199
3016 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3017 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3018 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3019 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3020 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3021 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3022 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3023 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3024 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3025 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3106 // FTEQW range #200-#299
3125 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3128 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3129 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3130 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3131 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3132 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3133 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3134 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3135 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3136 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3137 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3139 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3207 // CSQC range #300-#399
3208 NULL, // #300 void() clearscene (EXT_CSQC)
3209 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3210 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3211 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3212 NULL, // #304 void() renderscene (EXT_CSQC)
3213 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3214 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3215 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3216 NULL, // #308 void() R_EndPolygon
3218 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3219 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3223 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3224 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3225 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3226 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3227 NULL, // #319 void(string name) freepic (EXT_CSQC)
3228 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3229 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3230 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3231 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3232 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3233 NULL, // #325 void(void) drawresetcliparea
3238 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3239 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3240 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3241 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3242 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3243 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3244 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3245 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3246 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3247 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3248 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3249 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3250 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3251 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3252 NULL, // #344 vector() getmousepos (EXT_CSQC)
3253 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3254 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3255 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3256 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3257 NULL, // #349 float() isdemo (EXT_CSQC)
3258 VM_isserver, // #350 float() isserver (EXT_CSQC)
3259 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3260 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3261 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3262 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3268 NULL, // #360 float() readbyte (EXT_CSQC)
3269 NULL, // #361 float() readchar (EXT_CSQC)
3270 NULL, // #362 float() readshort (EXT_CSQC)
3271 NULL, // #363 float() readlong (EXT_CSQC)
3272 NULL, // #364 float() readcoord (EXT_CSQC)
3273 NULL, // #365 float() readangle (EXT_CSQC)
3274 NULL, // #366 string() readstring (EXT_CSQC)
3275 NULL, // #367 float() readfloat (EXT_CSQC)
3308 // LordHavoc's range #400-#499
3309 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3310 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3311 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3312 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3313 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3314 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3315 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3316 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3317 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)
3318 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3319 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3320 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3321 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3322 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3323 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3324 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3325 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3326 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3327 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3328 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3329 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3330 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3331 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3332 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3333 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3334 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3335 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3336 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3337 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3338 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3339 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3340 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3341 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3342 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3343 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3344 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3345 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3346 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3347 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3348 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3349 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3350 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3351 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3352 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3353 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3354 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3355 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3356 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3357 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3358 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3359 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3360 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3361 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3362 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3363 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3364 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3365 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3366 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3368 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3369 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3370 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3371 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3372 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3373 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3374 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3375 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3376 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3377 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3378 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3380 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3381 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3382 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3383 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3384 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3385 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3386 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3387 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3388 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3389 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3390 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3391 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3392 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3393 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3394 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3395 VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3403 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3404 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3405 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3406 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3407 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3408 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3409 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3410 VM_SV_WritePicture, // #501
3412 VM_whichpack, // #503 string(string) whichpack = #503;
3419 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3420 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3421 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3422 VM_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET)
3423 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3424 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3425 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3426 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3427 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3431 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3433 void VM_SV_Cmd_Init(void)
3438 void VM_SV_Cmd_Reset(void)
3440 if(prog->funcoffsets.SV_Shutdown)
3442 func_t s = prog->funcoffsets.SV_Shutdown;
3443 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3444 PRVM_ExecuteProgram(s,"SV_Shutdown() required");