6 //============================================================================
11 char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
22 "DP_CSQC_MULTIFRAME_INTERPOLATION "
38 "DP_ENT_CUSTOMCOLORMAP "
39 "DP_ENT_EXTERIORMODELTOCLIENT "
41 "DP_ENT_LOWPRECISION "
45 "DP_GFX_EXTERNALTEXTURES "
46 "DP_GFX_EXTERNALTEXTURES_PERMAP "
48 "DP_GFX_QUAKE3MODELTAGS "
51 "DP_GFX_MODEL_INTERPOLATION "
53 "DP_HALFLIFE_MAP_CVAR "
59 "DP_MOVETYPEBOUNCEMISSILE "
62 "DP_QC_ASINACOSATANATAN2TAN "
67 "DP_QC_CVAR_DEFSTRING "
68 "DP_QC_CVAR_DESCRIPTION "
75 "DP_QC_FINDCHAIN_TOFIELD "
76 "DP_QC_FINDCHAINFLAGS "
77 "DP_QC_FINDCHAINFLOAT "
83 "DP_QC_GETSURFACEPOINTATTRIBUTE "
85 "DP_QC_GETTAGINFO_BONEPROPERTIES "
88 "DP_QC_MULTIPLETEMPSTRINGS "
89 "DP_QC_NUM_FOR_EDICT "
91 "DP_QC_SINCOSSQRTPOW "
93 "DP_QC_STRINGBUFFERS "
94 "DP_QC_STRINGBUFFERS_CVARLIST "
95 "DP_QC_STRINGCOLORFUNCTIONS "
96 "DP_QC_STRING_CASE_FUNCTIONS "
98 "DP_QC_TOKENIZEBYSEPARATOR "
99 "DP_QC_TOKENIZE_CONSOLE "
102 "DP_QC_TRACE_MOVETYPE_HITMODEL "
103 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
104 "DP_QC_UNLIMITEDTEMPSTRINGS "
107 "DP_QC_VECTOANGLES_WITH_ROLL "
108 "DP_QC_VECTORVECTORS "
115 "DP_SND_DIRECTIONLESSATTNNONE "
122 "DP_SV_CLIENTCOLORS "
125 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
126 "DP_SV_DRAWONLYTOCLIENT "
129 "DP_SV_ENTITYCONTENTSTRANSITION "
130 "DP_SV_MODELFLAGS_AS_EFFECTS "
131 "DP_SV_MOVETYPESTEP_LANDEVENT "
133 "DP_SV_NODRAWTOCLIENT "
134 "DP_SV_ONENTITYNOSPAWNFUNCTION "
135 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
137 "DP_SV_PLAYERPHYSICS "
138 "DP_SV_POINTPARTICLES "
140 "DP_SV_PRECACHEANYTIME "
144 "DP_SV_ROTATINGBMODEL "
148 "DP_SV_SPAWNFUNC_PREFIX "
149 "DP_SV_WRITEPICTURE "
150 "DP_SV_WRITEUNTERMINATEDSTRING "
154 "DP_TE_EXPLOSIONRGB "
156 "DP_TE_PARTICLECUBE "
157 "DP_TE_PARTICLERAIN "
158 "DP_TE_PARTICLESNOW "
160 "DP_TE_QUADEFFECTS1 "
163 "DP_TE_STANDARDEFFECTBUILTINS "
164 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
170 "KRIMZON_SV_PARSECLIENTCOMMAND "
173 "NEXUIZ_PLAYERMODEL "
175 "PRYDON_CLIENTCURSOR "
176 "TENEBRAE_GFX_DLIGHTS "
179 //"EXT_CSQC " // not ready yet
186 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.
188 setorigin (entity, origin)
191 static void VM_SV_setorigin (void)
196 VM_SAFEPARMCOUNT(2, VM_setorigin);
198 e = PRVM_G_EDICT(OFS_PARM0);
199 if (e == prog->edicts)
201 VM_Warning("setorigin: can not modify world entity\n");
204 if (e->priv.server->free)
206 VM_Warning("setorigin: can not modify free entity\n");
209 org = PRVM_G_VECTOR(OFS_PARM1);
210 VectorCopy (org, e->fields.server->origin);
211 SV_LinkEdict (e, false);
214 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
215 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
219 for (i=0 ; i<3 ; i++)
221 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
223 // set derived values
224 VectorCopy (min, e->fields.server->mins);
225 VectorCopy (max, e->fields.server->maxs);
226 VectorSubtract (max, min, e->fields.server->size);
228 SV_LinkEdict (e, false);
235 the size box is rotated by the current angle
236 LordHavoc: no it isn't...
238 setsize (entity, minvector, maxvector)
241 static void VM_SV_setsize (void)
246 VM_SAFEPARMCOUNT(3, VM_setsize);
248 e = PRVM_G_EDICT(OFS_PARM0);
249 if (e == prog->edicts)
251 VM_Warning("setsize: can not modify world entity\n");
254 if (e->priv.server->free)
256 VM_Warning("setsize: can not modify free entity\n");
259 min = PRVM_G_VECTOR(OFS_PARM1);
260 max = PRVM_G_VECTOR(OFS_PARM2);
261 SetMinMaxSize (e, min, max, false);
269 setmodel(entity, model)
272 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
273 static void VM_SV_setmodel (void)
279 VM_SAFEPARMCOUNT(2, VM_setmodel);
281 e = PRVM_G_EDICT(OFS_PARM0);
282 if (e == prog->edicts)
284 VM_Warning("setmodel: can not modify world entity\n");
287 if (e->priv.server->free)
289 VM_Warning("setmodel: can not modify free entity\n");
292 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
293 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
294 e->fields.server->modelindex = i;
300 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
301 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
303 SetMinMaxSize (e, quakemins, quakemaxs, true);
306 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
313 single print to a specific client
315 sprint(clientent, value)
318 static void VM_SV_sprint (void)
322 char string[VM_STRINGTEMP_LENGTH];
324 VM_VarString(1, string, sizeof(string));
326 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
328 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
329 // LordHavoc: div0 requested that sprintto world operate like print
336 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
338 VM_Warning("tried to centerprint to a non-client\n");
342 client = svs.clients + entnum-1;
343 if (!client->netconnection)
346 MSG_WriteChar(&client->netconnection->message,svc_print);
347 MSG_WriteString(&client->netconnection->message, string);
355 single print to a specific client
357 centerprint(clientent, value)
360 static void VM_SV_centerprint (void)
364 char string[VM_STRINGTEMP_LENGTH];
366 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
368 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
370 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
372 VM_Warning("tried to centerprint to a non-client\n");
376 client = svs.clients + entnum-1;
377 if (!client->netconnection)
380 VM_VarString(1, string, sizeof(string));
381 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
382 MSG_WriteString(&client->netconnection->message, string);
389 particle(origin, color, count)
392 static void VM_SV_particle (void)
398 VM_SAFEPARMCOUNT(4, VM_SV_particle);
400 org = PRVM_G_VECTOR(OFS_PARM0);
401 dir = PRVM_G_VECTOR(OFS_PARM1);
402 color = PRVM_G_FLOAT(OFS_PARM2);
403 count = PRVM_G_FLOAT(OFS_PARM3);
404 SV_StartParticle (org, dir, (int)color, (int)count);
414 static void VM_SV_ambientsound (void)
418 float vol, attenuation;
421 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
423 pos = PRVM_G_VECTOR (OFS_PARM0);
424 samp = PRVM_G_STRING(OFS_PARM1);
425 vol = PRVM_G_FLOAT(OFS_PARM2);
426 attenuation = PRVM_G_FLOAT(OFS_PARM3);
428 // check to see if samp was properly precached
429 soundnum = SV_SoundIndex(samp, 1);
437 // add an svc_spawnambient command to the level signon packet
440 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
442 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
444 MSG_WriteVector(&sv.signon, pos, sv.protocol);
446 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
447 MSG_WriteShort (&sv.signon, soundnum);
449 MSG_WriteByte (&sv.signon, soundnum);
451 MSG_WriteByte (&sv.signon, (int)(vol*255));
452 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
460 Each entity can have eight independant sound sources, like voice,
463 Channel 0 is an auto-allocate channel, the others override anything
464 already running on that entity/channel pair.
466 An attenuation of 0 will play full volume everywhere in the level.
467 Larger attenuations will drop off.
471 static void VM_SV_sound (void)
475 prvm_edict_t *entity;
479 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
481 entity = PRVM_G_EDICT(OFS_PARM0);
482 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
483 sample = PRVM_G_STRING(OFS_PARM2);
484 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
485 attenuation = PRVM_G_FLOAT(OFS_PARM4);
488 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
492 if (volume < 0 || volume > 255)
494 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
498 if (attenuation < 0 || attenuation > 4)
500 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
504 if (channel < 0 || channel > 7)
506 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
510 SV_StartSound (entity, channel, sample, volume, attenuation);
517 Follows the same logic as VM_SV_sound, except instead of
518 an entity, an origin for the sound is provided, and channel
519 is omitted (since no entity is being tracked).
523 static void VM_SV_pointsound(void)
530 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
532 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
533 sample = PRVM_G_STRING(OFS_PARM1);
534 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
535 attenuation = PRVM_G_FLOAT(OFS_PARM3);
537 if (volume < 0 || volume > 255)
539 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
543 if (attenuation < 0 || attenuation > 4)
545 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
549 SV_StartPointSound (org, sample, volume, attenuation);
556 Used for use tracing and shot targeting
557 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
558 if the tryents flag is set.
560 traceline (vector1, vector2, movetype, ignore)
563 static void VM_SV_traceline (void)
570 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
572 prog->xfunction->builtinsprofile += 30;
574 v1 = PRVM_G_VECTOR(OFS_PARM0);
575 v2 = PRVM_G_VECTOR(OFS_PARM1);
576 move = (int)PRVM_G_FLOAT(OFS_PARM2);
577 ent = PRVM_G_EDICT(OFS_PARM3);
579 if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
580 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));
582 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
584 VM_SetTraceGlobals(&trace);
592 Used for use tracing and shot targeting
593 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
594 if the tryents flag is set.
596 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
599 // LordHavoc: added this for my own use, VERY useful, similar to traceline
600 static void VM_SV_tracebox (void)
602 float *v1, *v2, *m1, *m2;
607 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
609 prog->xfunction->builtinsprofile += 30;
611 v1 = PRVM_G_VECTOR(OFS_PARM0);
612 m1 = PRVM_G_VECTOR(OFS_PARM1);
613 m2 = PRVM_G_VECTOR(OFS_PARM2);
614 v2 = PRVM_G_VECTOR(OFS_PARM3);
615 move = (int)PRVM_G_FLOAT(OFS_PARM4);
616 ent = PRVM_G_EDICT(OFS_PARM5);
618 if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
619 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));
621 trace = SV_Move (v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
623 VM_SetTraceGlobals(&trace);
626 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
631 vec3_t original_origin;
632 vec3_t original_velocity;
633 vec3_t original_angles;
634 vec3_t original_avelocity;
638 VectorCopy(tossent->fields.server->origin , original_origin );
639 VectorCopy(tossent->fields.server->velocity , original_velocity );
640 VectorCopy(tossent->fields.server->angles , original_angles );
641 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
643 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
644 if (val != NULL && val->_float != 0)
645 gravity = val->_float;
648 gravity *= sv_gravity.value * 0.025;
650 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
652 SV_CheckVelocity (tossent);
653 tossent->fields.server->velocity[2] -= gravity;
654 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
655 VectorScale (tossent->fields.server->velocity, 0.05, move);
656 VectorAdd (tossent->fields.server->origin, move, end);
657 trace = SV_Move (tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
658 VectorCopy (trace.endpos, tossent->fields.server->origin);
659 tossent->fields.server->velocity[2] -= gravity;
661 if (trace.fraction < 1)
665 VectorCopy(original_origin , tossent->fields.server->origin );
666 VectorCopy(original_velocity , tossent->fields.server->velocity );
667 VectorCopy(original_angles , tossent->fields.server->angles );
668 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
673 static void VM_SV_tracetoss (void)
677 prvm_edict_t *ignore;
679 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
681 prog->xfunction->builtinsprofile += 600;
683 ent = PRVM_G_EDICT(OFS_PARM0);
684 if (ent == prog->edicts)
686 VM_Warning("tracetoss: can not use world entity\n");
689 ignore = PRVM_G_EDICT(OFS_PARM1);
691 trace = SV_Trace_Toss (ent, ignore);
693 VM_SetTraceGlobals(&trace);
696 //============================================================================
698 static int checkpvsbytes;
699 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
701 static int VM_SV_newcheckclient (int check)
707 // cycle to the next one
709 check = bound(1, check, svs.maxclients);
710 if (check == svs.maxclients)
718 prog->xfunction->builtinsprofile++;
720 if (i == svs.maxclients+1)
722 // look up the client's edict
723 ent = PRVM_EDICT_NUM(i);
724 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
725 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
727 // found a valid client (possibly the same one again)
731 // get the PVS for the entity
732 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
734 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
735 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
744 Returns a client (or object that has a client enemy) that would be a
747 If there is more than one valid option, they are cycled each frame
749 If (self.origin + self.viewofs) is not in the PVS of the current target,
750 it is not returned at all.
755 int c_invis, c_notvis;
756 static void VM_SV_checkclient (void)
758 prvm_edict_t *ent, *self;
761 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
763 // find a new check if on a new frame
764 if (sv.time - sv.lastchecktime >= 0.1)
766 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
767 sv.lastchecktime = sv.time;
770 // return check if it might be visible
771 ent = PRVM_EDICT_NUM(sv.lastcheck);
772 if (ent->priv.server->free || ent->fields.server->health <= 0)
774 VM_RETURN_EDICT(prog->edicts);
778 // if current entity can't possibly see the check entity, return 0
779 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
780 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
781 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
784 VM_RETURN_EDICT(prog->edicts);
788 // might be able to see it
790 VM_RETURN_EDICT(ent);
793 //============================================================================
799 Checks if an entity is in a point's PVS.
800 Should be fast but can be inexact.
802 float checkpvs(vector viewpos, entity viewee) = #240;
805 static void VM_SV_checkpvs (void)
808 prvm_edict_t *viewee;
812 static int fatpvsbytes;
813 static unsigned char fatpvs[MAX_MAP_LEAFS/8];
816 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
817 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
818 viewee = PRVM_G_EDICT(OFS_PARM1);
820 if(viewee->priv.server->free)
822 VM_Warning("checkpvs: can not check free entity\n");
823 PRVM_G_FLOAT(OFS_RETURN) = 4;
828 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
830 // no PVS support on this worldmodel... darn
831 PRVM_G_FLOAT(OFS_RETURN) = 3;
834 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
837 // viewpos isn't in any PVS... darn
838 PRVM_G_FLOAT(OFS_RETURN) = 2;
841 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
843 // using fat PVS like FTEQW does (slow)
844 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
846 // no PVS support on this worldmodel... darn
847 PRVM_G_FLOAT(OFS_RETURN) = 3;
850 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
853 // viewpos isn't in any PVS... darn
854 PRVM_G_FLOAT(OFS_RETURN) = 2;
857 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
866 Sends text over to the client's execution buffer
868 stuffcmd (clientent, value, ...)
871 static void VM_SV_stuffcmd (void)
875 char string[VM_STRINGTEMP_LENGTH];
877 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
879 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
880 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
882 VM_Warning("Can't stuffcmd to a non-client\n");
886 VM_VarString(1, string, sizeof(string));
889 host_client = svs.clients + entnum-1;
890 Host_ClientCommands ("%s", string);
898 Returns a chain of entities that have origins within a spherical area
900 findradius (origin, radius)
903 static void VM_SV_findradius (void)
905 prvm_edict_t *ent, *chain;
906 vec_t radius, radius2;
907 vec3_t org, eorg, mins, maxs;
910 prvm_edict_t *touchedicts[MAX_EDICTS];
913 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
916 chainfield = PRVM_G_INT(OFS_PARM2);
918 chainfield = prog->fieldoffsets.chain;
920 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
922 chain = (prvm_edict_t *)prog->edicts;
924 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
925 radius = PRVM_G_FLOAT(OFS_PARM1);
926 radius2 = radius * radius;
928 mins[0] = org[0] - (radius + 1);
929 mins[1] = org[1] - (radius + 1);
930 mins[2] = org[2] - (radius + 1);
931 maxs[0] = org[0] + (radius + 1);
932 maxs[1] = org[1] + (radius + 1);
933 maxs[2] = org[2] + (radius + 1);
934 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
935 if (numtouchedicts > MAX_EDICTS)
937 // this never happens
938 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
939 numtouchedicts = MAX_EDICTS;
941 for (i = 0;i < numtouchedicts;i++)
943 ent = touchedicts[i];
944 prog->xfunction->builtinsprofile++;
945 // Quake did not return non-solid entities but darkplaces does
946 // (note: this is the reason you can't blow up fallen zombies)
947 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
949 // LordHavoc: compare against bounding box rather than center so it
950 // doesn't miss large objects, and use DotProduct instead of Length
951 // for a major speedup
952 VectorSubtract(org, ent->fields.server->origin, eorg);
953 if (sv_gameplayfix_findradiusdistancetobox.integer)
955 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
956 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
957 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
960 VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
961 if (DotProduct(eorg, eorg) < radius2)
963 PRVM_EDICTFIELDVALUE(ent,chainfield)->edict = PRVM_EDICT_TO_PROG(chain);
968 VM_RETURN_EDICT(chain);
971 static void VM_SV_precache_sound (void)
973 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
974 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
977 static void VM_SV_precache_model (void)
979 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
980 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
981 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
988 float(float yaw, float dist[, settrace]) walkmove
991 static void VM_SV_walkmove (void)
1000 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1002 // assume failure if it returns early
1003 PRVM_G_FLOAT(OFS_RETURN) = 0;
1005 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1006 if (ent == prog->edicts)
1008 VM_Warning("walkmove: can not modify world entity\n");
1011 if (ent->priv.server->free)
1013 VM_Warning("walkmove: can not modify free entity\n");
1016 yaw = PRVM_G_FLOAT(OFS_PARM0);
1017 dist = PRVM_G_FLOAT(OFS_PARM1);
1018 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1020 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1023 yaw = yaw*M_PI*2 / 360;
1025 move[0] = cos(yaw)*dist;
1026 move[1] = sin(yaw)*dist;
1029 // save program state, because SV_movestep may call other progs
1030 oldf = prog->xfunction;
1031 oldself = prog->globals.server->self;
1033 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1036 // restore program state
1037 prog->xfunction = oldf;
1038 prog->globals.server->self = oldself;
1048 static void VM_SV_droptofloor (void)
1054 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1056 // assume failure if it returns early
1057 PRVM_G_FLOAT(OFS_RETURN) = 0;
1059 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1060 if (ent == prog->edicts)
1062 VM_Warning("droptofloor: can not modify world entity\n");
1065 if (ent->priv.server->free)
1067 VM_Warning("droptofloor: can not modify free entity\n");
1071 VectorCopy (ent->fields.server->origin, end);
1074 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1075 SV_UnstickEntity(ent);
1077 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1078 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1081 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]);
1082 VectorAdd(ent->fields.server->origin, offset, org);
1083 trace = SV_Move (org, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1084 VectorSubtract(trace.endpos, offset, trace.endpos);
1085 if (trace.startsolid)
1087 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]);
1088 SV_UnstickEntity(ent);
1089 SV_LinkEdict (ent, false);
1090 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1091 ent->fields.server->groundentity = 0;
1092 PRVM_G_FLOAT(OFS_RETURN) = 1;
1094 else if (trace.fraction < 1)
1096 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]);
1097 VectorCopy (trace.endpos, ent->fields.server->origin);
1098 SV_UnstickEntity(ent);
1099 SV_LinkEdict (ent, false);
1100 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1101 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1102 PRVM_G_FLOAT(OFS_RETURN) = 1;
1103 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1104 ent->priv.server->suspendedinairflag = true;
1109 if (trace.fraction != 1)
1111 if (trace.fraction < 1)
1112 VectorCopy (trace.endpos, ent->fields.server->origin);
1113 SV_LinkEdict (ent, false);
1114 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1115 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1116 PRVM_G_FLOAT(OFS_RETURN) = 1;
1117 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1118 ent->priv.server->suspendedinairflag = true;
1127 void(float style, string value) lightstyle
1130 static void VM_SV_lightstyle (void)
1137 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1139 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1140 val = PRVM_G_STRING(OFS_PARM1);
1142 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1143 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1146 // change the string in sv
1147 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1149 // send message to all clients on this server
1150 if (sv.state != ss_active)
1153 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1155 if (client->active && client->netconnection)
1157 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1158 MSG_WriteChar (&client->netconnection->message,style);
1159 MSG_WriteString (&client->netconnection->message, val);
1169 static void VM_SV_checkbottom (void)
1171 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1172 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1180 static void VM_SV_pointcontents (void)
1182 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1183 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1190 Pick a vector for the player to shoot along
1191 vector aim(entity, missilespeed)
1194 static void VM_SV_aim (void)
1196 prvm_edict_t *ent, *check, *bestent;
1197 vec3_t start, dir, end, bestdir;
1200 float dist, bestdist;
1203 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1205 // assume failure if it returns early
1206 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1207 // if sv_aim is so high it can't possibly accept anything, skip out early
1208 if (sv_aim.value >= 1)
1211 ent = PRVM_G_EDICT(OFS_PARM0);
1212 if (ent == prog->edicts)
1214 VM_Warning("aim: can not use world entity\n");
1217 if (ent->priv.server->free)
1219 VM_Warning("aim: can not use free entity\n");
1222 speed = PRVM_G_FLOAT(OFS_PARM1);
1224 VectorCopy (ent->fields.server->origin, start);
1227 // try sending a trace straight
1228 VectorCopy (prog->globals.server->v_forward, dir);
1229 VectorMA (start, 2048, dir, end);
1230 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1231 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1232 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1234 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1239 // try all possible entities
1240 VectorCopy (dir, bestdir);
1241 bestdist = sv_aim.value;
1244 check = PRVM_NEXT_EDICT(prog->edicts);
1245 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1247 prog->xfunction->builtinsprofile++;
1248 if (check->fields.server->takedamage != DAMAGE_AIM)
1252 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1253 continue; // don't aim at teammate
1254 for (j=0 ; j<3 ; j++)
1255 end[j] = check->fields.server->origin[j]
1256 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1257 VectorSubtract (end, start, dir);
1258 VectorNormalize (dir);
1259 dist = DotProduct (dir, prog->globals.server->v_forward);
1260 if (dist < bestdist)
1261 continue; // to far to turn
1262 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1263 if (tr.ent == check)
1264 { // can shoot at this one
1272 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1273 dist = DotProduct (dir, prog->globals.server->v_forward);
1274 VectorScale (prog->globals.server->v_forward, dist, end);
1276 VectorNormalize (end);
1277 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1281 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1286 ===============================================================================
1290 ===============================================================================
1293 #define MSG_BROADCAST 0 // unreliable to all
1294 #define MSG_ONE 1 // reliable to one (msg_entity)
1295 #define MSG_ALL 2 // reliable to all
1296 #define MSG_INIT 3 // write to the init string
1297 #define MSG_ENTITY 5
1299 sizebuf_t *WriteDest (void)
1305 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1309 return &sv.datagram;
1312 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1313 entnum = PRVM_NUM_FOR_EDICT(ent);
1314 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1316 VM_Warning ("WriteDest: tried to write to non-client\n");
1317 return &sv.reliable_datagram;
1320 return &svs.clients[entnum-1].netconnection->message;
1323 VM_Warning ("WriteDest: bad destination\n");
1325 return &sv.reliable_datagram;
1331 return sv.writeentitiestoclient_msg;
1337 static void VM_SV_WriteByte (void)
1339 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1340 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1343 static void VM_SV_WriteChar (void)
1345 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1346 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1349 static void VM_SV_WriteShort (void)
1351 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1352 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1355 static void VM_SV_WriteLong (void)
1357 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1358 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1361 static void VM_SV_WriteAngle (void)
1363 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1364 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1367 static void VM_SV_WriteCoord (void)
1369 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1370 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1373 static void VM_SV_WriteString (void)
1375 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1376 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1379 static void VM_SV_WriteUnterminatedString (void)
1381 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1382 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1386 static void VM_SV_WriteEntity (void)
1388 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1389 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1392 // writes a picture as at most size bytes of data
1394 // IMGNAME \0 SIZE(short) IMGDATA
1395 // if failed to read/compress:
1397 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1398 static void VM_SV_WritePicture (void)
1400 const char *imgname;
1404 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1406 imgname = PRVM_G_STRING(OFS_PARM1);
1407 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1411 MSG_WriteString(WriteDest(), imgname);
1412 if(Image_Compress(imgname, size, &buf, &size))
1415 MSG_WriteShort(WriteDest(), size);
1416 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1421 MSG_WriteShort(WriteDest(), 0);
1425 //////////////////////////////////////////////////////////
1427 static void VM_SV_makestatic (void)
1432 // allow 0 parameters due to an id1 qc bug in which this function is used
1433 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1434 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1436 if (prog->argc >= 1)
1437 ent = PRVM_G_EDICT(OFS_PARM0);
1439 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1440 if (ent == prog->edicts)
1442 VM_Warning("makestatic: can not modify world entity\n");
1445 if (ent->priv.server->free)
1447 VM_Warning("makestatic: can not modify free entity\n");
1452 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1457 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1458 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1459 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1461 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1463 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1464 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1465 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1469 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1470 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1471 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1474 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1475 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1476 for (i=0 ; i<3 ; i++)
1478 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1479 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1482 // throw the entity away now
1486 //=============================================================================
1493 static void VM_SV_setspawnparms (void)
1499 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1501 ent = PRVM_G_EDICT(OFS_PARM0);
1502 i = PRVM_NUM_FOR_EDICT(ent);
1503 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1505 Con_Print("tried to setspawnparms on a non-client\n");
1509 // copy spawn parms out of the client_t
1510 client = svs.clients + i-1;
1511 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1512 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1519 Returns a color vector indicating the lighting at the requested point.
1521 (Internal Operation note: actually measures the light beneath the point, just like
1522 the model lighting on the client)
1527 static void VM_SV_getlight (void)
1529 vec3_t ambientcolor, diffusecolor, diffusenormal;
1531 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1532 p = PRVM_G_VECTOR(OFS_PARM0);
1533 VectorClear(ambientcolor);
1534 VectorClear(diffusecolor);
1535 VectorClear(diffusenormal);
1536 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1537 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1538 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1543 unsigned char type; // 1/2/8 or other value if isn't used
1547 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1548 static int vm_customstats_last;
1550 void VM_CustomStats_Clear (void)
1554 Z_Free(vm_customstats);
1555 vm_customstats = NULL;
1556 vm_customstats_last = -1;
1560 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1568 for(i=0; i<vm_customstats_last+1 ;i++)
1570 if(!vm_customstats[i].type)
1572 switch(vm_customstats[i].type)
1574 //string as 16 bytes
1577 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1578 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1579 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1580 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1581 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1583 //float field sent as-is
1585 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1587 //integer value of float field
1589 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1597 // void(float index, float type, .void field) SV_AddStat = #232;
1598 // Set up an auto-sent player stat.
1599 // Client's get thier own fields sent to them. Index may not be less than 32.
1600 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1601 // 1: string (4 stats carrying a total of 16 charactures)
1602 // 2: float (one stat, float converted to an integer for transportation)
1603 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1604 static void VM_SV_AddStat (void)
1609 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1613 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1616 VM_Warning("PF_SV_AddStat: not enough memory\n");
1620 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1621 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1622 off = PRVM_G_INT (OFS_PARM2);
1627 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1630 if(i >= (MAX_CL_STATS-32))
1632 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1635 if(i > (MAX_CL_STATS-32-4) && type == 1)
1637 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1640 vm_customstats[i].type = type;
1641 vm_customstats[i].fieldoffset = off;
1642 if(vm_customstats_last < i)
1643 vm_customstats_last = i;
1650 copies data from one entity to another
1652 copyentity(src, dst)
1655 static void VM_SV_copyentity (void)
1657 prvm_edict_t *in, *out;
1658 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1659 in = PRVM_G_EDICT(OFS_PARM0);
1660 if (in == prog->edicts)
1662 VM_Warning("copyentity: can not read world entity\n");
1665 if (in->priv.server->free)
1667 VM_Warning("copyentity: can not read free entity\n");
1670 out = PRVM_G_EDICT(OFS_PARM1);
1671 if (out == prog->edicts)
1673 VM_Warning("copyentity: can not modify world entity\n");
1676 if (out->priv.server->free)
1678 VM_Warning("copyentity: can not modify free entity\n");
1681 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1682 SV_LinkEdict(out, false);
1690 sets the color of a client and broadcasts the update to all connected clients
1692 setcolor(clientent, value)
1695 static void VM_SV_setcolor (void)
1701 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1702 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1703 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1705 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1707 Con_Print("tried to setcolor a non-client\n");
1711 client = svs.clients + entnum-1;
1714 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1716 client->edict->fields.server->team = (i & 15) + 1;
1719 if (client->old_colors != client->colors)
1721 client->old_colors = client->colors;
1722 // send notification to all clients
1723 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1724 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1725 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1733 effect(origin, modelname, startframe, framecount, framerate)
1736 static void VM_SV_effect (void)
1740 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1741 s = PRVM_G_STRING(OFS_PARM1);
1744 VM_Warning("effect: no model specified\n");
1748 i = SV_ModelIndex(s, 1);
1751 VM_Warning("effect: model not precached\n");
1755 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1757 VM_Warning("effect: framecount < 1\n");
1761 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1763 VM_Warning("effect: framerate < 1\n");
1767 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));
1770 static void VM_SV_te_blood (void)
1772 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1773 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1775 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1776 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1778 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1779 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1780 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1782 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1783 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1784 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1786 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1787 SV_FlushBroadcastMessages();
1790 static void VM_SV_te_bloodshower (void)
1792 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1793 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1795 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1796 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1798 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1799 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1800 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1802 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1803 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1804 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1808 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1809 SV_FlushBroadcastMessages();
1812 static void VM_SV_te_explosionrgb (void)
1814 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1815 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1816 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1818 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1819 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1820 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1822 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1823 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1824 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1825 SV_FlushBroadcastMessages();
1828 static void VM_SV_te_particlecube (void)
1830 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1831 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1833 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1834 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
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_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1841 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1842 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1844 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1845 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1848 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1850 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1851 // gravity true/false
1852 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1854 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1855 SV_FlushBroadcastMessages();
1858 static void VM_SV_te_particlerain (void)
1860 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1861 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1863 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1864 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
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);
1870 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1874 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1875 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1876 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1878 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1880 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1881 SV_FlushBroadcastMessages();
1884 static void VM_SV_te_particlesnow (void)
1886 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1887 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1889 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1890 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1892 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1893 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1894 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1896 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1900 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1904 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1906 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1907 SV_FlushBroadcastMessages();
1910 static void VM_SV_te_spark (void)
1912 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1913 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1915 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1916 MSG_WriteByte(&sv.datagram, TE_SPARK);
1918 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1919 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1920 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1922 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1923 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1924 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1926 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1927 SV_FlushBroadcastMessages();
1930 static void VM_SV_te_gunshotquad (void)
1932 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1933 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1934 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
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_spikequad (void)
1944 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1945 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1946 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
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_superspikequad (void)
1956 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1957 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1958 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
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_explosionquad (void)
1968 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
1969 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1970 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
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_smallflash (void)
1980 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
1981 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1982 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
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_customflash (void)
1992 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
1993 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1995 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1996 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1998 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1999 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2000 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2002 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2004 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2006 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2007 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2008 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2009 SV_FlushBroadcastMessages();
2012 static void VM_SV_te_gunshot (void)
2014 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2015 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2016 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2018 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2019 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2020 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2021 SV_FlushBroadcastMessages();
2024 static void VM_SV_te_spike (void)
2026 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2027 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2028 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2030 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2031 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2032 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2033 SV_FlushBroadcastMessages();
2036 static void VM_SV_te_superspike (void)
2038 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2039 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2040 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2042 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2043 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2044 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2045 SV_FlushBroadcastMessages();
2048 static void VM_SV_te_explosion (void)
2050 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2051 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2052 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2054 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2055 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2056 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2057 SV_FlushBroadcastMessages();
2060 static void VM_SV_te_tarexplosion (void)
2062 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2063 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2064 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2066 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2067 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2068 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2069 SV_FlushBroadcastMessages();
2072 static void VM_SV_te_wizspike (void)
2074 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2075 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2076 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2078 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2079 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2080 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2081 SV_FlushBroadcastMessages();
2084 static void VM_SV_te_knightspike (void)
2086 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2087 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2088 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2090 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2091 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2092 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2093 SV_FlushBroadcastMessages();
2096 static void VM_SV_te_lavasplash (void)
2098 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2099 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2100 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2102 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2103 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2104 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2105 SV_FlushBroadcastMessages();
2108 static void VM_SV_te_teleport (void)
2110 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2111 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2112 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2114 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2115 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2116 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2117 SV_FlushBroadcastMessages();
2120 static void VM_SV_te_explosion2 (void)
2122 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2123 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2124 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2126 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2127 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2128 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2130 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2131 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2132 SV_FlushBroadcastMessages();
2135 static void VM_SV_te_lightning1 (void)
2137 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2138 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2139 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2141 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2143 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2144 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2145 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2147 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2148 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2149 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2150 SV_FlushBroadcastMessages();
2153 static void VM_SV_te_lightning2 (void)
2155 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2156 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2157 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2159 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2161 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2162 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2163 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2165 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2166 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2167 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2168 SV_FlushBroadcastMessages();
2171 static void VM_SV_te_lightning3 (void)
2173 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2174 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2175 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2177 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2179 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2180 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2181 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2183 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2184 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2185 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2186 SV_FlushBroadcastMessages();
2189 static void VM_SV_te_beam (void)
2191 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2192 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2193 MSG_WriteByte(&sv.datagram, TE_BEAM);
2195 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2197 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2198 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2199 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2201 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2202 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2203 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2204 SV_FlushBroadcastMessages();
2207 static void VM_SV_te_plasmaburn (void)
2209 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2210 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2211 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2212 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2213 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2214 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2215 SV_FlushBroadcastMessages();
2218 static void VM_SV_te_flamejet (void)
2220 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2221 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2222 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2224 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2225 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2226 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2230 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2232 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2233 SV_FlushBroadcastMessages();
2236 void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2239 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2241 bestdist = 1000000000;
2243 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2245 // clip original point to each triangle of the surface and find the
2246 // triangle that is closest
2247 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2248 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2249 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2250 TriangleNormal(v[0], v[1], v[2], facenormal);
2251 VectorNormalize(facenormal);
2252 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2253 VectorMA(p, offsetdist, facenormal, temp);
2254 for (j = 0, k = 2;j < 3;k = j, j++)
2256 VectorSubtract(v[k], v[j], edgenormal);
2257 CrossProduct(edgenormal, facenormal, sidenormal);
2258 VectorNormalize(sidenormal);
2259 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2261 VectorMA(temp, offsetdist, sidenormal, temp);
2263 dist = VectorDistance2(temp, p);
2264 if (bestdist > dist)
2267 VectorCopy(temp, out);
2272 static dp_model_t *getmodel(prvm_edict_t *ed)
2275 if (!ed || ed->priv.server->free)
2277 modelindex = (int)ed->fields.server->modelindex;
2278 if (modelindex < 1 || modelindex >= MAX_MODELS)
2280 return sv.models[modelindex];
2283 static msurface_t *getsurface(dp_model_t *model, int surfacenum)
2285 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2287 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2291 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2292 static void VM_SV_getsurfacenumpoints(void)
2295 msurface_t *surface;
2296 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints);
2297 // return 0 if no such surface
2298 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2300 PRVM_G_FLOAT(OFS_RETURN) = 0;
2304 // note: this (incorrectly) assumes it is a simple polygon
2305 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2307 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2308 static void VM_SV_getsurfacepoint(void)
2312 msurface_t *surface;
2314 VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint);
2315 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2316 ed = PRVM_G_EDICT(OFS_PARM0);
2317 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2319 // note: this (incorrectly) assumes it is a simple polygon
2320 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2321 if (pointnum < 0 || pointnum >= surface->num_vertices)
2323 // FIXME: implement rotation/scaling
2324 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2326 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
2327 // float SPA_POSITION = 0;
2328 // float SPA_S_AXIS = 1;
2329 // float SPA_T_AXIS = 2;
2330 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2331 // float SPA_TEXCOORDS0 = 4;
2332 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2333 // float SPA_LIGHTMAP0_COLOR = 6;
2334 static void VM_SV_getsurfacepointattribute(void)
2338 msurface_t *surface;
2342 VM_SAFEPARMCOUNT(4, VM_SV_getsurfacepoint);
2343 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2344 ed = PRVM_G_EDICT(OFS_PARM0);
2345 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2347 // note: this (incorrectly) assumes it is a simple polygon
2348 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2349 if (pointnum < 0 || pointnum >= surface->num_vertices)
2351 // FIXME: implement rotation/scaling
2352 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
2354 switch( attributetype ) {
2355 // float SPA_POSITION = 0;
2357 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2359 // float SPA_S_AXIS = 1;
2361 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2363 // float SPA_T_AXIS = 2;
2365 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2367 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2369 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2371 // float SPA_TEXCOORDS0 = 4;
2373 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2374 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
2375 ret[0] = texcoord[0];
2376 ret[1] = texcoord[1];
2380 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2382 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2383 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
2384 ret[0] = texcoord[0];
2385 ret[1] = texcoord[1];
2389 // float SPA_LIGHTMAP0_COLOR = 6;
2391 // ignore alpha for now..
2392 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2395 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2399 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2400 static void VM_SV_getsurfacenormal(void)
2403 msurface_t *surface;
2405 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal);
2406 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2407 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2409 // FIXME: implement rotation/scaling
2410 // note: this (incorrectly) assumes it is a simple polygon
2411 // note: this only returns the first triangle, so it doesn't work very
2412 // well for curved surfaces or arbitrary meshes
2413 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);
2414 VectorNormalize(normal);
2415 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2417 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2418 static void VM_SV_getsurfacetexture(void)
2421 msurface_t *surface;
2422 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture);
2423 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2424 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2426 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2428 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2429 static void VM_SV_getsurfacenearpoint(void)
2431 int surfacenum, best;
2433 vec_t dist, bestdist;
2436 msurface_t *surface;
2438 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint);
2439 PRVM_G_FLOAT(OFS_RETURN) = -1;
2440 ed = PRVM_G_EDICT(OFS_PARM0);
2441 point = PRVM_G_VECTOR(OFS_PARM1);
2443 if (!ed || ed->priv.server->free)
2445 model = getmodel(ed);
2446 if (!model || !model->num_surfaces)
2449 // FIXME: implement rotation/scaling
2450 VectorSubtract(point, ed->fields.server->origin, p);
2452 bestdist = 1000000000;
2453 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2455 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2456 // first see if the nearest point on the surface's box is closer than the previous match
2457 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2458 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2459 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2460 dist = VectorLength2(clipped);
2461 if (dist < bestdist)
2463 // it is, check the nearest point on the actual geometry
2464 clippointtosurface(model, surface, p, clipped);
2465 VectorSubtract(clipped, p, clipped);
2466 dist += VectorLength2(clipped);
2467 if (dist < bestdist)
2469 // that's closer too, store it as the best match
2475 PRVM_G_FLOAT(OFS_RETURN) = best;
2477 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2478 static void VM_SV_getsurfaceclippedpoint(void)
2482 msurface_t *surface;
2484 VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint);
2485 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2486 ed = PRVM_G_EDICT(OFS_PARM0);
2487 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2489 // FIXME: implement rotation/scaling
2490 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2491 clippointtosurface(model, surface, p, out);
2492 // FIXME: implement rotation/scaling
2493 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2496 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2497 //this function originally written by KrimZon, made shorter by LordHavoc
2498 static void VM_SV_clientcommand (void)
2500 client_t *temp_client;
2502 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2504 //find client for this entity
2505 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2506 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2508 Con_Print("PF_clientcommand: entity is not a client\n");
2512 temp_client = host_client;
2513 host_client = svs.clients + i;
2514 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2515 host_client = temp_client;
2518 //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)
2519 static void VM_SV_setattachment (void)
2521 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2522 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2523 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2527 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2529 if (e == prog->edicts)
2531 VM_Warning("setattachment: can not modify world entity\n");
2534 if (e->priv.server->free)
2536 VM_Warning("setattachment: can not modify free entity\n");
2540 if (tagentity == NULL)
2541 tagentity = prog->edicts;
2543 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2545 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2547 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2550 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2552 modelindex = (int)tagentity->fields.server->modelindex;
2553 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2555 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2557 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);
2560 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));
2564 /////////////////////////////////////////
2565 // DP_MD3_TAGINFO extension coded by VorteX
2567 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2572 i = (int)e->fields.server->modelindex;
2573 if (i < 1 || i >= MAX_MODELS)
2575 model = sv.models[i];
2577 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2580 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2589 Matrix4x4_CreateIdentity(tag_localmatrix);
2592 && (modelindex = (int)e->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2593 && (model = sv.models[(int)e->fields.server->modelindex])
2594 && model->animscenes)
2596 frame = (int)e->fields.server->frame;
2597 if (frame < 0 || frame >= model->numframes)
2600 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)e->fields.server->skin, model->animscenes[frame].firstframe, tagindex - 1, parentindex, tagname, tag_localmatrix);
2611 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2620 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2621 if (val && val->_float != 0)
2622 scale = val->_float;
2625 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 * cl_viewmodel_scale.value);
2630 ((modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[(int)ent->fields.server->modelindex]))
2632 model->type == mod_alias
2635 (((unsigned char)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.pflags)->_float) & PFLAGS_FULLDYNAMIC)
2637 ((gamemode == GAME_TENEBRAE) && ((unsigned int)ent->fields.server->effects & (16 | 32)))
2641 Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2], WTFsign * ent->fields.server->angles[0], ent->fields.server->angles[1], ent->fields.server->angles[2], scale);
2645 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2651 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2652 && (model = sv.models[(int)ent->fields.server->modelindex])
2653 && model->animscenes)
2655 // if model has wrong frame, engine automatically switches to model first frame
2656 frame = (int)ent->fields.server->frame;
2657 if (frame < 0 || frame >= model->numframes)
2659 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2661 *out = identitymatrix;
2665 // Warnings/errors code:
2666 // 0 - normal (everything all-right)
2669 // 3 - null or non-precached model
2670 // 4 - no tags with requested index
2671 // 5 - runaway loop at attachment chain
2672 extern cvar_t cl_bob;
2673 extern cvar_t cl_bobcycle;
2674 extern cvar_t cl_bobup;
2675 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2679 int modelindex, attachloop;
2680 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2683 *out = identitymatrix; // warnings and errors return identical matrix
2685 if (ent == prog->edicts)
2687 if (ent->priv.server->free)
2690 modelindex = (int)ent->fields.server->modelindex;
2691 if (modelindex <= 0 || modelindex > MAX_MODELS)
2694 model = sv.models[modelindex];
2696 tagmatrix = identitymatrix;
2697 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2701 if (attachloop >= 256) // prevent runaway looping
2703 // apply transformation by child's tagindex on parent entity and then
2704 // by parent entity itself
2705 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2706 if (ret && attachloop == 0)
2708 SV_GetEntityMatrix(ent, &entitymatrix, false);
2709 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2710 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2711 // next iteration we process the parent entity
2712 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2714 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2715 ent = PRVM_EDICT_NUM(val->edict);
2722 // RENDER_VIEWMODEL magic
2723 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2725 Matrix4x4_Copy(&tagmatrix, out);
2726 ent = PRVM_EDICT_NUM(val->edict);
2728 SV_GetEntityMatrix(ent, &entitymatrix, true);
2729 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2732 // Cl_bob, ported from rendering code
2733 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2736 // LordHavoc: this code is *weird*, but not replacable (I think it
2737 // should be done in QC on the server, but oh well, quake is quake)
2738 // LordHavoc: figured out bobup: the time at which the sin is at 180
2739 // degrees (which allows lengthening or squishing the peak or valley)
2740 cycle = sv.time/cl_bobcycle.value;
2741 cycle -= (int)cycle;
2742 if (cycle < cl_bobup.value)
2743 cycle = sin(M_PI * cycle / cl_bobup.value);
2745 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2746 // bob is proportional to velocity in the xy plane
2747 // (don't count Z, or jumping messes it up)
2748 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;
2749 bob = bob*0.3 + bob*0.7*cycle;
2750 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2757 //float(entity ent, string tagname) gettagindex;
2759 static void VM_SV_gettagindex (void)
2762 const char *tag_name;
2763 int modelindex, tag_index;
2765 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2767 ent = PRVM_G_EDICT(OFS_PARM0);
2768 tag_name = PRVM_G_STRING(OFS_PARM1);
2770 if (ent == prog->edicts)
2772 VM_Warning("gettagindex: can't affect world entity\n");
2775 if (ent->priv.server->free)
2777 VM_Warning("gettagindex: can't affect free entity\n");
2781 modelindex = (int)ent->fields.server->modelindex;
2783 if (modelindex <= 0 || modelindex > MAX_MODELS)
2784 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2787 tag_index = SV_GetTagIndex(ent, tag_name);
2789 if(developer.integer >= 100)
2790 Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2792 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2795 //vector(entity ent, float tagindex) gettaginfo;
2796 static void VM_SV_gettaginfo (void)
2800 matrix4x4_t tag_matrix;
2801 matrix4x4_t tag_localmatrix;
2803 const char *tagname;
2806 vec3_t fo, le, up, trans;
2808 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2810 e = PRVM_G_EDICT(OFS_PARM0);
2811 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2813 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2814 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, le, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2815 VectorScale(le, -1, prog->globals.server->v_right);
2816 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2817 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2819 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_parent)))
2820 val->_float = parentindex;
2821 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_name)))
2822 val->string = tagname ? PRVM_SetTempString(tagname) : 0;
2823 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_offset)))
2824 VectorCopy(trans, val->vector);
2825 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_forward)))
2826 VectorCopy(fo, val->vector);
2827 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_right)))
2828 VectorScale(le, -1, val->vector);
2829 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_up)))
2830 VectorCopy(up, val->vector);
2835 VM_Warning("gettagindex: can't affect world entity\n");
2838 VM_Warning("gettagindex: can't affect free entity\n");
2841 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2844 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2847 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2852 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2853 static void VM_SV_dropclient (void)
2856 client_t *oldhostclient;
2857 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2858 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2859 if (clientnum < 0 || clientnum >= svs.maxclients)
2861 VM_Warning("dropclient: not a client\n");
2864 if (!svs.clients[clientnum].active)
2866 VM_Warning("dropclient: that client slot is not connected\n");
2869 oldhostclient = host_client;
2870 host_client = svs.clients + clientnum;
2871 SV_DropClient(false);
2872 host_client = oldhostclient;
2875 //entity() spawnclient (DP_SV_BOTCLIENT)
2876 static void VM_SV_spawnclient (void)
2880 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2881 prog->xfunction->builtinsprofile += 2;
2883 for (i = 0;i < svs.maxclients;i++)
2885 if (!svs.clients[i].active)
2887 prog->xfunction->builtinsprofile += 100;
2888 SV_ConnectClient (i, NULL);
2889 // this has to be set or else ClientDisconnect won't be called
2890 // we assume the qc will call ClientConnect...
2891 svs.clients[i].clientconnectcalled = true;
2892 ed = PRVM_EDICT_NUM(i + 1);
2896 VM_RETURN_EDICT(ed);
2899 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2900 static void VM_SV_clienttype (void)
2903 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2904 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2905 if (clientnum < 0 || clientnum >= svs.maxclients)
2906 PRVM_G_FLOAT(OFS_RETURN) = 3;
2907 else if (!svs.clients[clientnum].active)
2908 PRVM_G_FLOAT(OFS_RETURN) = 0;
2909 else if (svs.clients[clientnum].netconnection)
2910 PRVM_G_FLOAT(OFS_RETURN) = 1;
2912 PRVM_G_FLOAT(OFS_RETURN) = 2;
2919 string(string key) serverkey
2922 void VM_SV_serverkey(void)
2924 char string[VM_STRINGTEMP_LENGTH];
2925 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2926 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2927 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2930 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2931 static void VM_SV_setmodelindex (void)
2936 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2938 e = PRVM_G_EDICT(OFS_PARM0);
2939 if (e == prog->edicts)
2941 VM_Warning("setmodelindex: can not modify world entity\n");
2944 if (e->priv.server->free)
2946 VM_Warning("setmodelindex: can not modify free entity\n");
2949 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2950 if (i <= 0 || i > MAX_MODELS)
2952 VM_Warning("setmodelindex: invalid modelindex\n");
2955 if (!sv.model_precache[i][0])
2957 VM_Warning("setmodelindex: model not precached\n");
2961 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2962 e->fields.server->modelindex = i;
2968 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2969 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2971 SetMinMaxSize (e, quakemins, quakemaxs, true);
2974 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2977 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2978 static void VM_SV_modelnameforindex (void)
2981 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2983 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2985 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2986 if (i <= 0 || i > MAX_MODELS)
2988 VM_Warning("modelnameforindex: invalid modelindex\n");
2991 if (!sv.model_precache[i][0])
2993 VM_Warning("modelnameforindex: model not precached\n");
2997 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
3000 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
3001 static void VM_SV_particleeffectnum (void)
3004 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
3005 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
3008 PRVM_G_FLOAT(OFS_RETURN) = i;
3011 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3012 static void VM_SV_trailparticles (void)
3014 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
3016 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3019 MSG_WriteByte(&sv.datagram, svc_trailparticles);
3020 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
3021 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
3022 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
3023 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
3024 SV_FlushBroadcastMessages();
3027 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
3028 static void VM_SV_pointparticles (void)
3030 int effectnum, count;
3032 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
3034 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3037 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
3038 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
3039 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
3040 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
3041 if (count == 1 && !VectorLength2(vel))
3044 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
3045 MSG_WriteShort(&sv.datagram, effectnum);
3046 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3050 // 1+2+12+12+2=29 bytes
3051 MSG_WriteByte(&sv.datagram, svc_pointparticles);
3052 MSG_WriteShort(&sv.datagram, effectnum);
3053 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3054 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
3055 MSG_WriteShort(&sv.datagram, count);
3058 SV_FlushBroadcastMessages();
3061 //PF_setpause, // void(float pause) setpause = #531;
3062 static void VM_SV_setpause(void) {
3064 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
3065 if (pauseValue != 0) { //pause the game
3067 sv.pausedstart = Sys_DoubleTime();
3068 } else { //disable pause, in case it was enabled
3069 if (sv.paused != 0) {
3074 // send notification to all clients
3075 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
3076 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
3079 prvm_builtin_t vm_sv_builtins[] = {
3080 NULL, // #0 NULL function (not callable) (QUAKE)
3081 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3082 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3083 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3084 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3085 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3086 VM_break, // #6 void() break (QUAKE)
3087 VM_random, // #7 float() random (QUAKE)
3088 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3089 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3090 VM_error, // #10 void(string e) error (QUAKE)
3091 VM_objerror, // #11 void(string e) objerror (QUAKE)
3092 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3093 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3094 VM_spawn, // #14 entity() spawn (QUAKE)
3095 VM_remove, // #15 void(entity e) remove (QUAKE)
3096 VM_SV_traceline, // #16 float(vector v1, vector v2, float tryents) traceline (QUAKE)
3097 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3098 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3099 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3100 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3101 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3102 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3103 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3104 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3105 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3106 VM_ftos, // #26 string(float f) ftos (QUAKE)
3107 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3108 VM_coredump, // #28 void() coredump (QUAKE)
3109 VM_traceon, // #29 void() traceon (QUAKE)
3110 VM_traceoff, // #30 void() traceoff (QUAKE)
3111 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3112 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3113 NULL, // #33 (QUAKE)
3114 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3115 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3116 VM_rint, // #36 float(float v) rint (QUAKE)
3117 VM_floor, // #37 float(float v) floor (QUAKE)
3118 VM_ceil, // #38 float(float v) ceil (QUAKE)
3119 NULL, // #39 (QUAKE)
3120 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3121 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3122 NULL, // #42 (QUAKE)
3123 VM_fabs, // #43 float(float f) fabs (QUAKE)
3124 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3125 VM_cvar, // #45 float(string s) cvar (QUAKE)
3126 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3127 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3128 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3129 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3130 NULL, // #50 (QUAKE)
3131 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3132 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3133 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3134 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3135 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3136 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3137 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3138 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3139 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3140 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3141 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3142 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3143 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3144 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3145 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3146 NULL, // #66 (QUAKE)
3147 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3148 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3149 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3150 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3151 NULL, // #71 (QUAKE)
3152 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3153 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3154 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3155 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3156 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3157 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3158 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3159 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3160 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3161 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3162 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3163 NULL, // #83 (QUAKE)
3164 NULL, // #84 (QUAKE)
3165 NULL, // #85 (QUAKE)
3166 NULL, // #86 (QUAKE)
3167 NULL, // #87 (QUAKE)
3168 NULL, // #88 (QUAKE)
3169 NULL, // #89 (QUAKE)
3170 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3171 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3172 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3173 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3174 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3175 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3176 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3177 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3178 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3179 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3180 // FrikaC and Telejano range #100-#199
3191 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3192 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3193 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3194 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3195 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3196 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3197 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3198 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3199 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3200 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3281 // FTEQW range #200-#299
3300 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3303 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3304 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3305 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3306 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3307 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3308 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3309 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3310 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3311 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3312 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3314 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3322 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3382 // CSQC range #300-#399
3383 NULL, // #300 void() clearscene (EXT_CSQC)
3384 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3385 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3386 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3387 NULL, // #304 void() renderscene (EXT_CSQC)
3388 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3389 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3390 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3391 NULL, // #308 void() R_EndPolygon
3393 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3394 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3398 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3399 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3400 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3401 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3402 NULL, // #319 void(string name) freepic (EXT_CSQC)
3403 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3404 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3405 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3406 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3407 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3408 NULL, // #325 void(void) drawresetcliparea
3413 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3414 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3415 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3416 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3417 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3418 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3419 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3420 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3421 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3422 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3423 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3424 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3425 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3426 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3427 NULL, // #344 vector() getmousepos (EXT_CSQC)
3428 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3429 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3430 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3431 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3432 NULL, // #349 float() isdemo (EXT_CSQC)
3433 VM_isserver, // #350 float() isserver (EXT_CSQC)
3434 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3435 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3436 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3437 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3443 NULL, // #360 float() readbyte (EXT_CSQC)
3444 NULL, // #361 float() readchar (EXT_CSQC)
3445 NULL, // #362 float() readshort (EXT_CSQC)
3446 NULL, // #363 float() readlong (EXT_CSQC)
3447 NULL, // #364 float() readcoord (EXT_CSQC)
3448 NULL, // #365 float() readangle (EXT_CSQC)
3449 NULL, // #366 string() readstring (EXT_CSQC)
3450 NULL, // #367 float() readfloat (EXT_CSQC)
3483 // LordHavoc's range #400-#499
3484 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3485 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3486 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3487 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3488 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3489 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3490 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3491 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3492 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)
3493 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3494 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3495 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3496 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3497 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3498 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3499 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3500 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3501 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3502 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3503 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3504 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3505 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3506 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3507 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3508 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3509 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3510 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3511 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3512 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3513 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3514 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3515 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3516 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3517 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3518 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3519 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3520 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3521 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3522 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3523 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3524 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3525 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3526 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3527 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3528 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3529 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3530 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3531 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3532 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3533 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3534 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3535 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3536 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3537 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3538 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3539 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3540 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3541 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3543 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3544 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3545 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3546 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3547 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3548 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3549 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3550 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3551 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3552 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3553 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3555 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3556 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3557 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3558 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3559 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3560 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3561 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3562 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3563 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3564 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3565 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3566 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3567 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3568 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3569 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3570 VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3578 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3579 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3580 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3581 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3582 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3583 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3584 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3585 VM_SV_WritePicture, // #501
3587 VM_whichpack, // #503 string(string) whichpack = #503;
3594 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3595 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3596 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3597 VM_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET)
3598 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3599 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3600 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3601 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3602 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3603 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3615 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3619 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3621 void VM_SV_Cmd_Init(void)
3626 void VM_SV_Cmd_Reset(void)
3628 if(prog->funcoffsets.SV_Shutdown)
3630 func_t s = prog->funcoffsets.SV_Shutdown;
3631 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3632 PRVM_ExecuteProgram(s,"SV_Shutdown() required");