6 //============================================================================
11 char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
22 "DP_CSQC_MULTIFRAME_INTERPOLATION "
38 "DP_ENT_CUSTOMCOLORMAP "
39 "DP_ENT_EXTERIORMODELTOCLIENT "
42 "DP_ENT_LOWPRECISION "
46 "DP_GFX_EXTERNALTEXTURES "
47 "DP_GFX_EXTERNALTEXTURES_PERMAP "
49 "DP_GFX_QUAKE3MODELTAGS "
52 "DP_GFX_MODEL_INTERPOLATION "
54 "DP_HALFLIFE_MAP_CVAR "
60 "DP_MOVETYPEBOUNCEMISSILE "
63 "DP_QC_ASINACOSATANATAN2TAN "
68 "DP_QC_CVAR_DEFSTRING "
69 "DP_QC_CVAR_DESCRIPTION "
75 "DP_QC_EXTRESPONSEPACKET "
77 "DP_QC_FINDCHAIN_TOFIELD "
78 "DP_QC_FINDCHAINFLAGS "
79 "DP_QC_FINDCHAINFLOAT "
85 "DP_QC_GETSURFACEPOINTATTRIBUTE "
87 "DP_QC_GETTAGINFO_BONEPROPERTIES "
89 "DP_QC_GETTIME_CDTRACK "
91 "DP_QC_MULTIPLETEMPSTRINGS "
92 "DP_QC_NUM_FOR_EDICT "
94 "DP_QC_SINCOSSQRTPOW "
96 "DP_QC_STRINGBUFFERS "
97 "DP_QC_STRINGBUFFERS_CVARLIST "
98 "DP_QC_STRINGCOLORFUNCTIONS "
99 "DP_QC_STRING_CASE_FUNCTIONS "
101 "DP_QC_TOKENIZEBYSEPARATOR "
102 "DP_QC_TOKENIZE_CONSOLE "
105 "DP_QC_TRACE_MOVETYPE_HITMODEL "
106 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
107 "DP_QC_UNLIMITEDTEMPSTRINGS "
110 "DP_QC_VECTOANGLES_WITH_ROLL "
111 "DP_QC_VECTORVECTORS "
118 "DP_SND_DIRECTIONLESSATTNNONE "
125 "DP_SV_BOUNCEFACTOR "
126 "DP_SV_CLIENTCOLORS "
129 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
130 "DP_SV_DRAWONLYTOCLIENT "
133 "DP_SV_ENTITYCONTENTSTRANSITION "
134 "DP_SV_MODELFLAGS_AS_EFFECTS "
135 "DP_SV_MOVETYPESTEP_LANDEVENT "
137 "DP_SV_NODRAWTOCLIENT "
138 "DP_SV_ONENTITYNOSPAWNFUNCTION "
139 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
141 "DP_SV_PLAYERPHYSICS "
142 "DP_SV_POINTPARTICLES "
144 "DP_SV_PRECACHEANYTIME "
148 "DP_SV_ROTATINGBMODEL "
152 "DP_SV_SPAWNFUNC_PREFIX "
153 "DP_SV_WRITEPICTURE "
154 "DP_SV_WRITEUNTERMINATEDSTRING "
158 "DP_TE_EXPLOSIONRGB "
160 "DP_TE_PARTICLECUBE "
161 "DP_TE_PARTICLERAIN "
162 "DP_TE_PARTICLESNOW "
164 "DP_TE_QUADEFFECTS1 "
167 "DP_TE_STANDARDEFFECTBUILTINS "
168 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
170 "DP_LIGHTSTYLE_STATICVALUE "
175 "KRIMZON_SV_PARSECLIENTCOMMAND "
178 "NEXUIZ_PLAYERMODEL "
180 "PRYDON_CLIENTCURSOR "
181 "TENEBRAE_GFX_DLIGHTS "
184 "DP_CSQC_SPAWNPARTICLE "
185 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
186 "DP_CSQC_ENTITYNOCULL "
187 //"EXT_CSQC " // not ready yet
194 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.
196 setorigin (entity, origin)
199 static void VM_SV_setorigin (void)
204 VM_SAFEPARMCOUNT(2, VM_setorigin);
206 e = PRVM_G_EDICT(OFS_PARM0);
207 if (e == prog->edicts)
209 VM_Warning("setorigin: can not modify world entity\n");
212 if (e->priv.server->free)
214 VM_Warning("setorigin: can not modify free entity\n");
217 org = PRVM_G_VECTOR(OFS_PARM1);
218 VectorCopy (org, e->fields.server->origin);
222 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
223 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
227 for (i=0 ; i<3 ; i++)
229 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
231 // set derived values
232 VectorCopy (min, e->fields.server->mins);
233 VectorCopy (max, e->fields.server->maxs);
234 VectorSubtract (max, min, e->fields.server->size);
243 the size box is rotated by the current angle
244 LordHavoc: no it isn't...
246 setsize (entity, minvector, maxvector)
249 static void VM_SV_setsize (void)
254 VM_SAFEPARMCOUNT(3, VM_setsize);
256 e = PRVM_G_EDICT(OFS_PARM0);
257 if (e == prog->edicts)
259 VM_Warning("setsize: can not modify world entity\n");
262 if (e->priv.server->free)
264 VM_Warning("setsize: can not modify free entity\n");
267 min = PRVM_G_VECTOR(OFS_PARM1);
268 max = PRVM_G_VECTOR(OFS_PARM2);
269 SetMinMaxSize (e, min, max, false);
277 setmodel(entity, model)
280 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
281 static void VM_SV_setmodel (void)
287 VM_SAFEPARMCOUNT(2, VM_setmodel);
289 e = PRVM_G_EDICT(OFS_PARM0);
290 if (e == prog->edicts)
292 VM_Warning("setmodel: can not modify world entity\n");
295 if (e->priv.server->free)
297 VM_Warning("setmodel: can not modify free entity\n");
300 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
301 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
302 e->fields.server->modelindex = i;
308 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
309 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
311 SetMinMaxSize (e, quakemins, quakemaxs, true);
314 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
321 single print to a specific client
323 sprint(clientent, value)
326 static void VM_SV_sprint (void)
330 char string[VM_STRINGTEMP_LENGTH];
332 VM_VarString(1, string, sizeof(string));
334 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
336 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
337 // LordHavoc: div0 requested that sprintto world operate like print
344 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
346 VM_Warning("tried to centerprint to a non-client\n");
350 client = svs.clients + entnum-1;
351 if (!client->netconnection)
354 MSG_WriteChar(&client->netconnection->message,svc_print);
355 MSG_WriteString(&client->netconnection->message, string);
363 single print to a specific client
365 centerprint(clientent, value)
368 static void VM_SV_centerprint (void)
372 char string[VM_STRINGTEMP_LENGTH];
374 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
376 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
378 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
380 VM_Warning("tried to centerprint to a non-client\n");
384 client = svs.clients + entnum-1;
385 if (!client->netconnection)
388 VM_VarString(1, string, sizeof(string));
389 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
390 MSG_WriteString(&client->netconnection->message, string);
397 particle(origin, color, count)
400 static void VM_SV_particle (void)
406 VM_SAFEPARMCOUNT(4, VM_SV_particle);
408 org = PRVM_G_VECTOR(OFS_PARM0);
409 dir = PRVM_G_VECTOR(OFS_PARM1);
410 color = PRVM_G_FLOAT(OFS_PARM2);
411 count = PRVM_G_FLOAT(OFS_PARM3);
412 SV_StartParticle (org, dir, (int)color, (int)count);
422 static void VM_SV_ambientsound (void)
426 float vol, attenuation;
429 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
431 pos = PRVM_G_VECTOR (OFS_PARM0);
432 samp = PRVM_G_STRING(OFS_PARM1);
433 vol = PRVM_G_FLOAT(OFS_PARM2);
434 attenuation = PRVM_G_FLOAT(OFS_PARM3);
436 // check to see if samp was properly precached
437 soundnum = SV_SoundIndex(samp, 1);
445 // add an svc_spawnambient command to the level signon packet
448 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
450 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
452 MSG_WriteVector(&sv.signon, pos, sv.protocol);
454 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
455 MSG_WriteShort (&sv.signon, soundnum);
457 MSG_WriteByte (&sv.signon, soundnum);
459 MSG_WriteByte (&sv.signon, (int)(vol*255));
460 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
468 Each entity can have eight independant sound sources, like voice,
471 Channel 0 is an auto-allocate channel, the others override anything
472 already running on that entity/channel pair.
474 An attenuation of 0 will play full volume everywhere in the level.
475 Larger attenuations will drop off.
479 static void VM_SV_sound (void)
483 prvm_edict_t *entity;
487 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
489 entity = PRVM_G_EDICT(OFS_PARM0);
490 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
491 sample = PRVM_G_STRING(OFS_PARM2);
492 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
493 attenuation = PRVM_G_FLOAT(OFS_PARM4);
496 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
500 if (volume < 0 || volume > 255)
502 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
506 if (attenuation < 0 || attenuation > 4)
508 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
512 if (channel < 0 || channel > 7)
514 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
518 SV_StartSound (entity, channel, sample, volume, attenuation);
525 Follows the same logic as VM_SV_sound, except instead of
526 an entity, an origin for the sound is provided, and channel
527 is omitted (since no entity is being tracked).
531 static void VM_SV_pointsound(void)
538 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
540 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
541 sample = PRVM_G_STRING(OFS_PARM1);
542 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
543 attenuation = PRVM_G_FLOAT(OFS_PARM3);
545 if (volume < 0 || volume > 255)
547 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
551 if (attenuation < 0 || attenuation > 4)
553 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
557 SV_StartPointSound (org, sample, volume, attenuation);
564 Used for use tracing and shot targeting
565 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
566 if the tryents flag is set.
568 traceline (vector1, vector2, movetype, ignore)
571 static void VM_SV_traceline (void)
578 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
580 prog->xfunction->builtinsprofile += 30;
582 v1 = PRVM_G_VECTOR(OFS_PARM0);
583 v2 = PRVM_G_VECTOR(OFS_PARM1);
584 move = (int)PRVM_G_FLOAT(OFS_PARM2);
585 ent = PRVM_G_EDICT(OFS_PARM3);
587 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]))
588 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));
590 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
592 VM_SetTraceGlobals(&trace);
600 Used for use tracing and shot targeting
601 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
602 if the tryents flag is set.
604 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
607 // LordHavoc: added this for my own use, VERY useful, similar to traceline
608 static void VM_SV_tracebox (void)
610 float *v1, *v2, *m1, *m2;
615 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
617 prog->xfunction->builtinsprofile += 30;
619 v1 = PRVM_G_VECTOR(OFS_PARM0);
620 m1 = PRVM_G_VECTOR(OFS_PARM1);
621 m2 = PRVM_G_VECTOR(OFS_PARM2);
622 v2 = PRVM_G_VECTOR(OFS_PARM3);
623 move = (int)PRVM_G_FLOAT(OFS_PARM4);
624 ent = PRVM_G_EDICT(OFS_PARM5);
626 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]))
627 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));
629 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
631 VM_SetTraceGlobals(&trace);
634 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
639 vec3_t original_origin;
640 vec3_t original_velocity;
641 vec3_t original_angles;
642 vec3_t original_avelocity;
646 VectorCopy(tossent->fields.server->origin , original_origin );
647 VectorCopy(tossent->fields.server->velocity , original_velocity );
648 VectorCopy(tossent->fields.server->angles , original_angles );
649 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
651 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
652 if (val != NULL && val->_float != 0)
653 gravity = val->_float;
656 gravity *= sv_gravity.value * 0.025;
658 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
660 SV_CheckVelocity (tossent);
661 tossent->fields.server->velocity[2] -= gravity;
662 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
663 VectorScale (tossent->fields.server->velocity, 0.05, move);
664 VectorAdd (tossent->fields.server->origin, move, end);
665 trace = SV_TraceBox(tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
666 VectorCopy (trace.endpos, tossent->fields.server->origin);
667 tossent->fields.server->velocity[2] -= gravity;
669 if (trace.fraction < 1)
673 VectorCopy(original_origin , tossent->fields.server->origin );
674 VectorCopy(original_velocity , tossent->fields.server->velocity );
675 VectorCopy(original_angles , tossent->fields.server->angles );
676 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
681 static void VM_SV_tracetoss (void)
685 prvm_edict_t *ignore;
687 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
689 prog->xfunction->builtinsprofile += 600;
691 ent = PRVM_G_EDICT(OFS_PARM0);
692 if (ent == prog->edicts)
694 VM_Warning("tracetoss: can not use world entity\n");
697 ignore = PRVM_G_EDICT(OFS_PARM1);
699 trace = SV_Trace_Toss (ent, ignore);
701 VM_SetTraceGlobals(&trace);
704 //============================================================================
706 static int checkpvsbytes;
707 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
709 static int VM_SV_newcheckclient (int check)
715 // cycle to the next one
717 check = bound(1, check, svs.maxclients);
718 if (check == svs.maxclients)
726 prog->xfunction->builtinsprofile++;
728 if (i == svs.maxclients+1)
730 // look up the client's edict
731 ent = PRVM_EDICT_NUM(i);
732 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
733 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
735 // found a valid client (possibly the same one again)
739 // get the PVS for the entity
740 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
742 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
743 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
752 Returns a client (or object that has a client enemy) that would be a
755 If there is more than one valid option, they are cycled each frame
757 If (self.origin + self.viewofs) is not in the PVS of the current target,
758 it is not returned at all.
763 int c_invis, c_notvis;
764 static void VM_SV_checkclient (void)
766 prvm_edict_t *ent, *self;
769 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
771 // find a new check if on a new frame
772 if (sv.time - sv.lastchecktime >= 0.1)
774 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
775 sv.lastchecktime = sv.time;
778 // return check if it might be visible
779 ent = PRVM_EDICT_NUM(sv.lastcheck);
780 if (ent->priv.server->free || ent->fields.server->health <= 0)
782 VM_RETURN_EDICT(prog->edicts);
786 // if current entity can't possibly see the check entity, return 0
787 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
788 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
789 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
792 VM_RETURN_EDICT(prog->edicts);
796 // might be able to see it
798 VM_RETURN_EDICT(ent);
801 //============================================================================
807 Checks if an entity is in a point's PVS.
808 Should be fast but can be inexact.
810 float checkpvs(vector viewpos, entity viewee) = #240;
813 static void VM_SV_checkpvs (void)
816 prvm_edict_t *viewee;
820 static int fatpvsbytes;
821 static unsigned char fatpvs[MAX_MAP_LEAFS/8];
824 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
825 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
826 viewee = PRVM_G_EDICT(OFS_PARM1);
828 if(viewee->priv.server->free)
830 VM_Warning("checkpvs: can not check free entity\n");
831 PRVM_G_FLOAT(OFS_RETURN) = 4;
836 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
838 // no PVS support on this worldmodel... darn
839 PRVM_G_FLOAT(OFS_RETURN) = 3;
842 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
845 // viewpos isn't in any PVS... darn
846 PRVM_G_FLOAT(OFS_RETURN) = 2;
849 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
851 // using fat PVS like FTEQW does (slow)
852 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
854 // no PVS support on this worldmodel... darn
855 PRVM_G_FLOAT(OFS_RETURN) = 3;
858 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
861 // viewpos isn't in any PVS... darn
862 PRVM_G_FLOAT(OFS_RETURN) = 2;
865 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
874 Sends text over to the client's execution buffer
876 stuffcmd (clientent, value, ...)
879 static void VM_SV_stuffcmd (void)
883 char string[VM_STRINGTEMP_LENGTH];
885 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
887 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
888 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
890 VM_Warning("Can't stuffcmd to a non-client\n");
894 VM_VarString(1, string, sizeof(string));
897 host_client = svs.clients + entnum-1;
898 Host_ClientCommands ("%s", string);
906 Returns a chain of entities that have origins within a spherical area
908 findradius (origin, radius)
911 static void VM_SV_findradius (void)
913 prvm_edict_t *ent, *chain;
914 vec_t radius, radius2;
915 vec3_t org, eorg, mins, maxs;
918 prvm_edict_t *touchedicts[MAX_EDICTS];
921 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
924 chainfield = PRVM_G_INT(OFS_PARM2);
926 chainfield = prog->fieldoffsets.chain;
928 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
930 chain = (prvm_edict_t *)prog->edicts;
932 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
933 radius = PRVM_G_FLOAT(OFS_PARM1);
934 radius2 = radius * radius;
936 mins[0] = org[0] - (radius + 1);
937 mins[1] = org[1] - (radius + 1);
938 mins[2] = org[2] - (radius + 1);
939 maxs[0] = org[0] + (radius + 1);
940 maxs[1] = org[1] + (radius + 1);
941 maxs[2] = org[2] + (radius + 1);
942 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
943 if (numtouchedicts > MAX_EDICTS)
945 // this never happens
946 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
947 numtouchedicts = MAX_EDICTS;
949 for (i = 0;i < numtouchedicts;i++)
951 ent = touchedicts[i];
952 prog->xfunction->builtinsprofile++;
953 // Quake did not return non-solid entities but darkplaces does
954 // (note: this is the reason you can't blow up fallen zombies)
955 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
957 // LordHavoc: compare against bounding box rather than center so it
958 // doesn't miss large objects, and use DotProduct instead of Length
959 // for a major speedup
960 VectorSubtract(org, ent->fields.server->origin, eorg);
961 if (sv_gameplayfix_findradiusdistancetobox.integer)
963 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
964 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
965 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
968 VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
969 if (DotProduct(eorg, eorg) < radius2)
971 PRVM_EDICTFIELDVALUE(ent,chainfield)->edict = PRVM_EDICT_TO_PROG(chain);
976 VM_RETURN_EDICT(chain);
979 static void VM_SV_precache_sound (void)
981 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
982 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
985 static void VM_SV_precache_model (void)
987 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
988 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
989 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
996 float(float yaw, float dist[, settrace]) walkmove
999 static void VM_SV_walkmove (void)
1008 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1010 // assume failure if it returns early
1011 PRVM_G_FLOAT(OFS_RETURN) = 0;
1013 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1014 if (ent == prog->edicts)
1016 VM_Warning("walkmove: can not modify world entity\n");
1019 if (ent->priv.server->free)
1021 VM_Warning("walkmove: can not modify free entity\n");
1024 yaw = PRVM_G_FLOAT(OFS_PARM0);
1025 dist = PRVM_G_FLOAT(OFS_PARM1);
1026 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1028 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1031 yaw = yaw*M_PI*2 / 360;
1033 move[0] = cos(yaw)*dist;
1034 move[1] = sin(yaw)*dist;
1037 // save program state, because SV_movestep may call other progs
1038 oldf = prog->xfunction;
1039 oldself = prog->globals.server->self;
1041 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1044 // restore program state
1045 prog->xfunction = oldf;
1046 prog->globals.server->self = oldself;
1056 static void VM_SV_droptofloor (void)
1062 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1064 // assume failure if it returns early
1065 PRVM_G_FLOAT(OFS_RETURN) = 0;
1067 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1068 if (ent == prog->edicts)
1070 VM_Warning("droptofloor: can not modify world entity\n");
1073 if (ent->priv.server->free)
1075 VM_Warning("droptofloor: can not modify free entity\n");
1079 VectorCopy (ent->fields.server->origin, end);
1082 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1083 SV_UnstickEntity(ent);
1085 trace = SV_TraceBox(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1086 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1089 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]);
1090 VectorAdd(ent->fields.server->origin, offset, org);
1091 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1092 VectorSubtract(trace.endpos, offset, trace.endpos);
1093 if (trace.startsolid)
1095 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]);
1096 SV_UnstickEntity(ent);
1098 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1099 ent->fields.server->groundentity = 0;
1100 PRVM_G_FLOAT(OFS_RETURN) = 1;
1102 else if (trace.fraction < 1)
1104 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]);
1105 VectorCopy (trace.endpos, ent->fields.server->origin);
1106 SV_UnstickEntity(ent);
1108 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1109 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1110 PRVM_G_FLOAT(OFS_RETURN) = 1;
1111 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1112 ent->priv.server->suspendedinairflag = true;
1117 if (trace.fraction != 1)
1119 if (trace.fraction < 1)
1120 VectorCopy (trace.endpos, ent->fields.server->origin);
1122 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1123 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1124 PRVM_G_FLOAT(OFS_RETURN) = 1;
1125 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1126 ent->priv.server->suspendedinairflag = true;
1135 void(float style, string value) lightstyle
1138 static void VM_SV_lightstyle (void)
1145 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1147 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1148 val = PRVM_G_STRING(OFS_PARM1);
1150 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1151 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1154 // change the string in sv
1155 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1157 // send message to all clients on this server
1158 if (sv.state != ss_active)
1161 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1163 if (client->active && client->netconnection)
1165 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1166 MSG_WriteChar (&client->netconnection->message,style);
1167 MSG_WriteString (&client->netconnection->message, val);
1177 static void VM_SV_checkbottom (void)
1179 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1180 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1188 static void VM_SV_pointcontents (void)
1190 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1191 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1198 Pick a vector for the player to shoot along
1199 vector aim(entity, missilespeed)
1202 static void VM_SV_aim (void)
1204 prvm_edict_t *ent, *check, *bestent;
1205 vec3_t start, dir, end, bestdir;
1208 float dist, bestdist;
1211 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1213 // assume failure if it returns early
1214 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1215 // if sv_aim is so high it can't possibly accept anything, skip out early
1216 if (sv_aim.value >= 1)
1219 ent = PRVM_G_EDICT(OFS_PARM0);
1220 if (ent == prog->edicts)
1222 VM_Warning("aim: can not use world entity\n");
1225 if (ent->priv.server->free)
1227 VM_Warning("aim: can not use free entity\n");
1230 speed = PRVM_G_FLOAT(OFS_PARM1);
1232 VectorCopy (ent->fields.server->origin, start);
1235 // try sending a trace straight
1236 VectorCopy (prog->globals.server->v_forward, dir);
1237 VectorMA (start, 2048, dir, end);
1238 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1239 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1240 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1242 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1247 // try all possible entities
1248 VectorCopy (dir, bestdir);
1249 bestdist = sv_aim.value;
1252 check = PRVM_NEXT_EDICT(prog->edicts);
1253 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1255 prog->xfunction->builtinsprofile++;
1256 if (check->fields.server->takedamage != DAMAGE_AIM)
1260 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1261 continue; // don't aim at teammate
1262 for (j=0 ; j<3 ; j++)
1263 end[j] = check->fields.server->origin[j]
1264 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1265 VectorSubtract (end, start, dir);
1266 VectorNormalize (dir);
1267 dist = DotProduct (dir, prog->globals.server->v_forward);
1268 if (dist < bestdist)
1269 continue; // to far to turn
1270 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1271 if (tr.ent == check)
1272 { // can shoot at this one
1280 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1281 dist = DotProduct (dir, prog->globals.server->v_forward);
1282 VectorScale (prog->globals.server->v_forward, dist, end);
1284 VectorNormalize (end);
1285 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1289 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1294 ===============================================================================
1298 ===============================================================================
1301 #define MSG_BROADCAST 0 // unreliable to all
1302 #define MSG_ONE 1 // reliable to one (msg_entity)
1303 #define MSG_ALL 2 // reliable to all
1304 #define MSG_INIT 3 // write to the init string
1305 #define MSG_ENTITY 5
1307 sizebuf_t *WriteDest (void)
1313 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1317 return &sv.datagram;
1320 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1321 entnum = PRVM_NUM_FOR_EDICT(ent);
1322 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1324 VM_Warning ("WriteDest: tried to write to non-client\n");
1325 return &sv.reliable_datagram;
1328 return &svs.clients[entnum-1].netconnection->message;
1331 VM_Warning ("WriteDest: bad destination\n");
1333 return &sv.reliable_datagram;
1339 return sv.writeentitiestoclient_msg;
1345 static void VM_SV_WriteByte (void)
1347 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1348 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1351 static void VM_SV_WriteChar (void)
1353 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1354 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1357 static void VM_SV_WriteShort (void)
1359 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1360 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1363 static void VM_SV_WriteLong (void)
1365 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1366 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1369 static void VM_SV_WriteAngle (void)
1371 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1372 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1375 static void VM_SV_WriteCoord (void)
1377 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1378 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1381 static void VM_SV_WriteString (void)
1383 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1384 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1387 static void VM_SV_WriteUnterminatedString (void)
1389 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1390 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1394 static void VM_SV_WriteEntity (void)
1396 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1397 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1400 // writes a picture as at most size bytes of data
1402 // IMGNAME \0 SIZE(short) IMGDATA
1403 // if failed to read/compress:
1405 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1406 static void VM_SV_WritePicture (void)
1408 const char *imgname;
1412 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1414 imgname = PRVM_G_STRING(OFS_PARM1);
1415 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1419 MSG_WriteString(WriteDest(), imgname);
1420 if(Image_Compress(imgname, size, &buf, &size))
1423 MSG_WriteShort(WriteDest(), size);
1424 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1429 MSG_WriteShort(WriteDest(), 0);
1433 //////////////////////////////////////////////////////////
1435 static void VM_SV_makestatic (void)
1440 // allow 0 parameters due to an id1 qc bug in which this function is used
1441 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1442 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1444 if (prog->argc >= 1)
1445 ent = PRVM_G_EDICT(OFS_PARM0);
1447 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1448 if (ent == prog->edicts)
1450 VM_Warning("makestatic: can not modify world entity\n");
1453 if (ent->priv.server->free)
1455 VM_Warning("makestatic: can not modify free entity\n");
1460 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1465 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1466 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1467 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1469 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1471 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1472 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1473 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1477 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1478 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1479 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1482 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1483 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1484 for (i=0 ; i<3 ; i++)
1486 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1487 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1490 // throw the entity away now
1494 //=============================================================================
1501 static void VM_SV_setspawnparms (void)
1507 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1509 ent = PRVM_G_EDICT(OFS_PARM0);
1510 i = PRVM_NUM_FOR_EDICT(ent);
1511 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1513 Con_Print("tried to setspawnparms on a non-client\n");
1517 // copy spawn parms out of the client_t
1518 client = svs.clients + i-1;
1519 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1520 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1527 Returns a color vector indicating the lighting at the requested point.
1529 (Internal Operation note: actually measures the light beneath the point, just like
1530 the model lighting on the client)
1535 static void VM_SV_getlight (void)
1537 vec3_t ambientcolor, diffusecolor, diffusenormal;
1539 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1540 p = PRVM_G_VECTOR(OFS_PARM0);
1541 VectorClear(ambientcolor);
1542 VectorClear(diffusecolor);
1543 VectorClear(diffusenormal);
1544 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1545 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1546 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1551 unsigned char type; // 1/2/8 or other value if isn't used
1555 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1556 static int vm_customstats_last;
1558 void VM_CustomStats_Clear (void)
1562 Z_Free(vm_customstats);
1563 vm_customstats = NULL;
1564 vm_customstats_last = -1;
1568 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1576 for(i=0; i<vm_customstats_last+1 ;i++)
1578 if(!vm_customstats[i].type)
1580 switch(vm_customstats[i].type)
1582 //string as 16 bytes
1585 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1586 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1587 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1588 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1589 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1591 //float field sent as-is
1593 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1595 //integer value of float field
1597 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1605 // void(float index, float type, .void field) SV_AddStat = #232;
1606 // Set up an auto-sent player stat.
1607 // Client's get thier own fields sent to them. Index may not be less than 32.
1608 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1609 // 1: string (4 stats carrying a total of 16 charactures)
1610 // 2: float (one stat, float converted to an integer for transportation)
1611 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1612 static void VM_SV_AddStat (void)
1617 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1621 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1624 VM_Warning("PF_SV_AddStat: not enough memory\n");
1628 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1629 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1630 off = PRVM_G_INT (OFS_PARM2);
1635 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1638 if(i >= (MAX_CL_STATS-32))
1640 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1643 if(i > (MAX_CL_STATS-32-4) && type == 1)
1645 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1648 vm_customstats[i].type = type;
1649 vm_customstats[i].fieldoffset = off;
1650 if(vm_customstats_last < i)
1651 vm_customstats_last = i;
1658 copies data from one entity to another
1660 copyentity(src, dst)
1663 static void VM_SV_copyentity (void)
1665 prvm_edict_t *in, *out;
1666 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1667 in = PRVM_G_EDICT(OFS_PARM0);
1668 if (in == prog->edicts)
1670 VM_Warning("copyentity: can not read world entity\n");
1673 if (in->priv.server->free)
1675 VM_Warning("copyentity: can not read free entity\n");
1678 out = PRVM_G_EDICT(OFS_PARM1);
1679 if (out == prog->edicts)
1681 VM_Warning("copyentity: can not modify world entity\n");
1684 if (out->priv.server->free)
1686 VM_Warning("copyentity: can not modify free entity\n");
1689 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1698 sets the color of a client and broadcasts the update to all connected clients
1700 setcolor(clientent, value)
1703 static void VM_SV_setcolor (void)
1709 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1710 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1711 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1713 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1715 Con_Print("tried to setcolor a non-client\n");
1719 client = svs.clients + entnum-1;
1722 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1724 client->edict->fields.server->team = (i & 15) + 1;
1727 if (client->old_colors != client->colors)
1729 client->old_colors = client->colors;
1730 // send notification to all clients
1731 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1732 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1733 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1741 effect(origin, modelname, startframe, framecount, framerate)
1744 static void VM_SV_effect (void)
1748 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1749 s = PRVM_G_STRING(OFS_PARM1);
1752 VM_Warning("effect: no model specified\n");
1756 i = SV_ModelIndex(s, 1);
1759 VM_Warning("effect: model not precached\n");
1763 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1765 VM_Warning("effect: framecount < 1\n");
1769 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1771 VM_Warning("effect: framerate < 1\n");
1775 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));
1778 static void VM_SV_te_blood (void)
1780 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1781 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1783 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1784 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1786 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1787 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1788 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1790 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1791 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1792 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1794 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1795 SV_FlushBroadcastMessages();
1798 static void VM_SV_te_bloodshower (void)
1800 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1801 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1803 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1804 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1808 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1810 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1812 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1814 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1816 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1817 SV_FlushBroadcastMessages();
1820 static void VM_SV_te_explosionrgb (void)
1822 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1823 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1824 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1826 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1827 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1828 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1830 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1831 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1832 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1833 SV_FlushBroadcastMessages();
1836 static void VM_SV_te_particlecube (void)
1838 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1839 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1841 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1842 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1844 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1845 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1848 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1849 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1850 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1852 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1853 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1854 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1856 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1858 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1859 // gravity true/false
1860 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1862 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1863 SV_FlushBroadcastMessages();
1866 static void VM_SV_te_particlerain (void)
1868 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1869 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1871 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1872 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1874 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1875 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1876 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1878 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1879 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1880 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1882 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1883 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1884 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1886 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1888 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1889 SV_FlushBroadcastMessages();
1892 static void VM_SV_te_particlesnow (void)
1894 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1895 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1897 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1898 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1900 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1912 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1914 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1915 SV_FlushBroadcastMessages();
1918 static void VM_SV_te_spark (void)
1920 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1921 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1923 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1924 MSG_WriteByte(&sv.datagram, TE_SPARK);
1926 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1930 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1931 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1932 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1934 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1935 SV_FlushBroadcastMessages();
1938 static void VM_SV_te_gunshotquad (void)
1940 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1941 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1942 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1944 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1945 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1947 SV_FlushBroadcastMessages();
1950 static void VM_SV_te_spikequad (void)
1952 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1953 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1954 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1959 SV_FlushBroadcastMessages();
1962 static void VM_SV_te_superspikequad (void)
1964 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1965 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1966 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1970 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1971 SV_FlushBroadcastMessages();
1974 static void VM_SV_te_explosionquad (void)
1976 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
1977 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1978 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1980 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1983 SV_FlushBroadcastMessages();
1986 static void VM_SV_te_smallflash (void)
1988 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
1989 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1990 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1992 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1993 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1994 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1995 SV_FlushBroadcastMessages();
1998 static void VM_SV_te_customflash (void)
2000 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2001 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2003 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2004 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2006 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2007 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2008 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2010 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2012 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2014 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2015 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2016 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2017 SV_FlushBroadcastMessages();
2020 static void VM_SV_te_gunshot (void)
2022 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2023 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2024 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2026 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2028 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2029 SV_FlushBroadcastMessages();
2032 static void VM_SV_te_spike (void)
2034 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2035 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2036 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2038 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2039 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2040 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2041 SV_FlushBroadcastMessages();
2044 static void VM_SV_te_superspike (void)
2046 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2047 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2048 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2050 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2052 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2053 SV_FlushBroadcastMessages();
2056 static void VM_SV_te_explosion (void)
2058 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2059 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2060 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2062 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2063 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2064 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2065 SV_FlushBroadcastMessages();
2068 static void VM_SV_te_tarexplosion (void)
2070 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2071 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2072 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2074 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2075 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2076 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2077 SV_FlushBroadcastMessages();
2080 static void VM_SV_te_wizspike (void)
2082 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2083 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2084 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2086 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2087 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2088 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2089 SV_FlushBroadcastMessages();
2092 static void VM_SV_te_knightspike (void)
2094 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2095 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2096 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2098 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2099 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2100 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2101 SV_FlushBroadcastMessages();
2104 static void VM_SV_te_lavasplash (void)
2106 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2107 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2108 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2110 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2111 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2112 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2113 SV_FlushBroadcastMessages();
2116 static void VM_SV_te_teleport (void)
2118 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2119 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2120 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2122 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2123 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2124 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2125 SV_FlushBroadcastMessages();
2128 static void VM_SV_te_explosion2 (void)
2130 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2131 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2132 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2134 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2135 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2136 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2138 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2139 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2140 SV_FlushBroadcastMessages();
2143 static void VM_SV_te_lightning1 (void)
2145 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2146 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2147 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2149 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2151 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2152 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2153 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2155 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2156 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2157 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2158 SV_FlushBroadcastMessages();
2161 static void VM_SV_te_lightning2 (void)
2163 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2164 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2165 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2167 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2169 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2170 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2171 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2173 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2174 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2175 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2176 SV_FlushBroadcastMessages();
2179 static void VM_SV_te_lightning3 (void)
2181 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2182 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2183 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2185 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2187 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2188 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2189 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2191 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2192 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2193 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2194 SV_FlushBroadcastMessages();
2197 static void VM_SV_te_beam (void)
2199 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2200 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2201 MSG_WriteByte(&sv.datagram, TE_BEAM);
2203 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2205 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2206 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2207 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2209 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2210 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2211 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2212 SV_FlushBroadcastMessages();
2215 static void VM_SV_te_plasmaburn (void)
2217 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2218 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2219 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2220 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2221 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2222 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2223 SV_FlushBroadcastMessages();
2226 static void VM_SV_te_flamejet (void)
2228 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2229 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2230 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2232 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2234 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2236 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2237 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2238 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2240 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2241 SV_FlushBroadcastMessages();
2244 void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2247 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2249 bestdist = 1000000000;
2251 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2253 // clip original point to each triangle of the surface and find the
2254 // triangle that is closest
2255 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2256 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2257 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2258 TriangleNormal(v[0], v[1], v[2], facenormal);
2259 VectorNormalize(facenormal);
2260 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2261 VectorMA(p, offsetdist, facenormal, temp);
2262 for (j = 0, k = 2;j < 3;k = j, j++)
2264 VectorSubtract(v[k], v[j], edgenormal);
2265 CrossProduct(edgenormal, facenormal, sidenormal);
2266 VectorNormalize(sidenormal);
2267 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2269 VectorMA(temp, offsetdist, sidenormal, temp);
2271 dist = VectorDistance2(temp, p);
2272 if (bestdist > dist)
2275 VectorCopy(temp, out);
2280 static dp_model_t *getmodel(prvm_edict_t *ed)
2283 if (!ed || ed->priv.server->free)
2285 modelindex = (int)ed->fields.server->modelindex;
2286 if (modelindex < 1 || modelindex >= MAX_MODELS)
2288 return sv.models[modelindex];
2291 static msurface_t *getsurface(dp_model_t *model, int surfacenum)
2293 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2295 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2299 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2300 static void VM_SV_getsurfacenumpoints(void)
2303 msurface_t *surface;
2304 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints);
2305 // return 0 if no such surface
2306 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2308 PRVM_G_FLOAT(OFS_RETURN) = 0;
2312 // note: this (incorrectly) assumes it is a simple polygon
2313 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2315 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2316 static void VM_SV_getsurfacepoint(void)
2320 msurface_t *surface;
2322 VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint);
2323 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2324 ed = PRVM_G_EDICT(OFS_PARM0);
2325 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2327 // note: this (incorrectly) assumes it is a simple polygon
2328 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2329 if (pointnum < 0 || pointnum >= surface->num_vertices)
2331 // FIXME: implement rotation/scaling
2332 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2334 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
2335 // float SPA_POSITION = 0;
2336 // float SPA_S_AXIS = 1;
2337 // float SPA_T_AXIS = 2;
2338 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2339 // float SPA_TEXCOORDS0 = 4;
2340 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2341 // float SPA_LIGHTMAP0_COLOR = 6;
2342 static void VM_SV_getsurfacepointattribute(void)
2346 msurface_t *surface;
2350 VM_SAFEPARMCOUNT(4, VM_SV_getsurfacepoint);
2351 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2352 ed = PRVM_G_EDICT(OFS_PARM0);
2353 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2355 // note: this (incorrectly) assumes it is a simple polygon
2356 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2357 if (pointnum < 0 || pointnum >= surface->num_vertices)
2359 // FIXME: implement rotation/scaling
2360 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
2362 switch( attributetype ) {
2363 // float SPA_POSITION = 0;
2365 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2367 // float SPA_S_AXIS = 1;
2369 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2371 // float SPA_T_AXIS = 2;
2373 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2375 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2377 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2379 // float SPA_TEXCOORDS0 = 4;
2381 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2382 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
2383 ret[0] = texcoord[0];
2384 ret[1] = texcoord[1];
2388 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2390 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2391 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
2392 ret[0] = texcoord[0];
2393 ret[1] = texcoord[1];
2397 // float SPA_LIGHTMAP0_COLOR = 6;
2399 // ignore alpha for now..
2400 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2403 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2407 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2408 static void VM_SV_getsurfacenormal(void)
2411 msurface_t *surface;
2413 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal);
2414 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2415 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2417 // FIXME: implement rotation/scaling
2418 // note: this (incorrectly) assumes it is a simple polygon
2419 // note: this only returns the first triangle, so it doesn't work very
2420 // well for curved surfaces or arbitrary meshes
2421 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);
2422 VectorNormalize(normal);
2423 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2425 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2426 static void VM_SV_getsurfacetexture(void)
2429 msurface_t *surface;
2430 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture);
2431 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2432 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2434 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2436 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2437 static void VM_SV_getsurfacenearpoint(void)
2439 int surfacenum, best;
2441 vec_t dist, bestdist;
2444 msurface_t *surface;
2446 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint);
2447 PRVM_G_FLOAT(OFS_RETURN) = -1;
2448 ed = PRVM_G_EDICT(OFS_PARM0);
2449 point = PRVM_G_VECTOR(OFS_PARM1);
2451 if (!ed || ed->priv.server->free)
2453 model = getmodel(ed);
2454 if (!model || !model->num_surfaces)
2457 // FIXME: implement rotation/scaling
2458 VectorSubtract(point, ed->fields.server->origin, p);
2460 bestdist = 1000000000;
2461 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2463 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2464 // first see if the nearest point on the surface's box is closer than the previous match
2465 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2466 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2467 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2468 dist = VectorLength2(clipped);
2469 if (dist < bestdist)
2471 // it is, check the nearest point on the actual geometry
2472 clippointtosurface(model, surface, p, clipped);
2473 VectorSubtract(clipped, p, clipped);
2474 dist += VectorLength2(clipped);
2475 if (dist < bestdist)
2477 // that's closer too, store it as the best match
2483 PRVM_G_FLOAT(OFS_RETURN) = best;
2485 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2486 static void VM_SV_getsurfaceclippedpoint(void)
2490 msurface_t *surface;
2492 VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint);
2493 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2494 ed = PRVM_G_EDICT(OFS_PARM0);
2495 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2497 // FIXME: implement rotation/scaling
2498 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2499 clippointtosurface(model, surface, p, out);
2500 // FIXME: implement rotation/scaling
2501 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2504 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2505 //this function originally written by KrimZon, made shorter by LordHavoc
2506 static void VM_SV_clientcommand (void)
2508 client_t *temp_client;
2510 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2512 //find client for this entity
2513 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2514 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2516 Con_Print("PF_clientcommand: entity is not a client\n");
2520 temp_client = host_client;
2521 host_client = svs.clients + i;
2522 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2523 host_client = temp_client;
2526 //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)
2527 static void VM_SV_setattachment (void)
2529 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2530 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2531 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2535 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2537 if (e == prog->edicts)
2539 VM_Warning("setattachment: can not modify world entity\n");
2542 if (e->priv.server->free)
2544 VM_Warning("setattachment: can not modify free entity\n");
2548 if (tagentity == NULL)
2549 tagentity = prog->edicts;
2551 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2553 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2555 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2558 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2560 modelindex = (int)tagentity->fields.server->modelindex;
2561 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2563 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2565 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);
2568 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));
2572 /////////////////////////////////////////
2573 // DP_MD3_TAGINFO extension coded by VorteX
2575 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2580 i = (int)e->fields.server->modelindex;
2581 if (i < 1 || i >= MAX_MODELS)
2583 model = sv.models[i];
2585 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2588 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2597 Matrix4x4_CreateIdentity(tag_localmatrix);
2600 && (modelindex = (int)e->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2601 && (model = sv.models[(int)e->fields.server->modelindex])
2602 && model->animscenes)
2604 frame = (int)e->fields.server->frame;
2605 if (frame < 0 || frame >= model->numframes)
2608 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)e->fields.server->skin, model->animscenes[frame].firstframe, tagindex - 1, parentindex, tagname, tag_localmatrix);
2619 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2623 float pitchsign = 1;
2626 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2627 if (val && val->_float != 0)
2628 scale = val->_float;
2631 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);
2634 pitchsign = SV_GetPitchSign(ent);
2635 Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2], pitchsign * ent->fields.server->angles[0], ent->fields.server->angles[1], ent->fields.server->angles[2], scale);
2639 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2645 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2646 && (model = sv.models[(int)ent->fields.server->modelindex])
2647 && model->animscenes)
2649 // if model has wrong frame, engine automatically switches to model first frame
2650 frame = (int)ent->fields.server->frame;
2651 if (frame < 0 || frame >= model->numframes)
2653 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2655 *out = identitymatrix;
2659 // Warnings/errors code:
2660 // 0 - normal (everything all-right)
2663 // 3 - null or non-precached model
2664 // 4 - no tags with requested index
2665 // 5 - runaway loop at attachment chain
2666 extern cvar_t cl_bob;
2667 extern cvar_t cl_bobcycle;
2668 extern cvar_t cl_bobup;
2669 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2673 int modelindex, attachloop;
2674 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2677 *out = identitymatrix; // warnings and errors return identical matrix
2679 if (ent == prog->edicts)
2681 if (ent->priv.server->free)
2684 modelindex = (int)ent->fields.server->modelindex;
2685 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2688 model = sv.models[modelindex];
2690 tagmatrix = identitymatrix;
2691 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2695 if (attachloop >= 256) // prevent runaway looping
2697 // apply transformation by child's tagindex on parent entity and then
2698 // by parent entity itself
2699 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2700 if (ret && attachloop == 0)
2702 SV_GetEntityMatrix(ent, &entitymatrix, false);
2703 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2704 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2705 // next iteration we process the parent entity
2706 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2708 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2709 ent = PRVM_EDICT_NUM(val->edict);
2716 // RENDER_VIEWMODEL magic
2717 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2719 Matrix4x4_Copy(&tagmatrix, out);
2720 ent = PRVM_EDICT_NUM(val->edict);
2722 SV_GetEntityMatrix(ent, &entitymatrix, true);
2723 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2726 // Cl_bob, ported from rendering code
2727 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2730 // LordHavoc: this code is *weird*, but not replacable (I think it
2731 // should be done in QC on the server, but oh well, quake is quake)
2732 // LordHavoc: figured out bobup: the time at which the sin is at 180
2733 // degrees (which allows lengthening or squishing the peak or valley)
2734 cycle = sv.time/cl_bobcycle.value;
2735 cycle -= (int)cycle;
2736 if (cycle < cl_bobup.value)
2737 cycle = sin(M_PI * cycle / cl_bobup.value);
2739 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2740 // bob is proportional to velocity in the xy plane
2741 // (don't count Z, or jumping messes it up)
2742 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;
2743 bob = bob*0.3 + bob*0.7*cycle;
2744 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2751 //float(entity ent, string tagname) gettagindex;
2753 static void VM_SV_gettagindex (void)
2756 const char *tag_name;
2757 int modelindex, tag_index;
2759 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2761 ent = PRVM_G_EDICT(OFS_PARM0);
2762 tag_name = PRVM_G_STRING(OFS_PARM1);
2764 if (ent == prog->edicts)
2766 VM_Warning("gettagindex: can't affect world entity\n");
2769 if (ent->priv.server->free)
2771 VM_Warning("gettagindex: can't affect free entity\n");
2775 modelindex = (int)ent->fields.server->modelindex;
2777 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2778 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2781 tag_index = SV_GetTagIndex(ent, tag_name);
2783 if(developer.integer >= 100)
2784 Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2786 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2789 //vector(entity ent, float tagindex) gettaginfo;
2790 static void VM_SV_gettaginfo (void)
2794 matrix4x4_t tag_matrix;
2795 matrix4x4_t tag_localmatrix;
2797 const char *tagname;
2800 vec3_t fo, le, up, trans;
2802 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2804 e = PRVM_G_EDICT(OFS_PARM0);
2805 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2807 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2808 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, le, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2809 VectorScale(le, -1, prog->globals.server->v_right);
2810 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2811 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2813 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_parent)))
2814 val->_float = parentindex;
2815 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_name)))
2816 val->string = tagname ? PRVM_SetTempString(tagname) : 0;
2817 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_offset)))
2818 VectorCopy(trans, val->vector);
2819 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_forward)))
2820 VectorCopy(fo, val->vector);
2821 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_right)))
2822 VectorScale(le, -1, val->vector);
2823 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_up)))
2824 VectorCopy(up, val->vector);
2829 VM_Warning("gettagindex: can't affect world entity\n");
2832 VM_Warning("gettagindex: can't affect free entity\n");
2835 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2838 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2841 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2846 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2847 static void VM_SV_dropclient (void)
2850 client_t *oldhostclient;
2851 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2852 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2853 if (clientnum < 0 || clientnum >= svs.maxclients)
2855 VM_Warning("dropclient: not a client\n");
2858 if (!svs.clients[clientnum].active)
2860 VM_Warning("dropclient: that client slot is not connected\n");
2863 oldhostclient = host_client;
2864 host_client = svs.clients + clientnum;
2865 SV_DropClient(false);
2866 host_client = oldhostclient;
2869 //entity() spawnclient (DP_SV_BOTCLIENT)
2870 static void VM_SV_spawnclient (void)
2874 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2875 prog->xfunction->builtinsprofile += 2;
2877 for (i = 0;i < svs.maxclients;i++)
2879 if (!svs.clients[i].active)
2881 prog->xfunction->builtinsprofile += 100;
2882 SV_ConnectClient (i, NULL);
2883 // this has to be set or else ClientDisconnect won't be called
2884 // we assume the qc will call ClientConnect...
2885 svs.clients[i].clientconnectcalled = true;
2886 ed = PRVM_EDICT_NUM(i + 1);
2890 VM_RETURN_EDICT(ed);
2893 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2894 static void VM_SV_clienttype (void)
2897 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2898 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2899 if (clientnum < 0 || clientnum >= svs.maxclients)
2900 PRVM_G_FLOAT(OFS_RETURN) = 3;
2901 else if (!svs.clients[clientnum].active)
2902 PRVM_G_FLOAT(OFS_RETURN) = 0;
2903 else if (svs.clients[clientnum].netconnection)
2904 PRVM_G_FLOAT(OFS_RETURN) = 1;
2906 PRVM_G_FLOAT(OFS_RETURN) = 2;
2913 string(string key) serverkey
2916 void VM_SV_serverkey(void)
2918 char string[VM_STRINGTEMP_LENGTH];
2919 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2920 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2921 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2924 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2925 static void VM_SV_setmodelindex (void)
2930 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2932 e = PRVM_G_EDICT(OFS_PARM0);
2933 if (e == prog->edicts)
2935 VM_Warning("setmodelindex: can not modify world entity\n");
2938 if (e->priv.server->free)
2940 VM_Warning("setmodelindex: can not modify free entity\n");
2943 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2944 if (i <= 0 || i >= MAX_MODELS)
2946 VM_Warning("setmodelindex: invalid modelindex\n");
2949 if (!sv.model_precache[i][0])
2951 VM_Warning("setmodelindex: model not precached\n");
2955 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2956 e->fields.server->modelindex = i;
2962 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2963 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2965 SetMinMaxSize (e, quakemins, quakemaxs, true);
2968 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2971 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2972 static void VM_SV_modelnameforindex (void)
2975 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2977 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2979 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2980 if (i <= 0 || i >= MAX_MODELS)
2982 VM_Warning("modelnameforindex: invalid modelindex\n");
2985 if (!sv.model_precache[i][0])
2987 VM_Warning("modelnameforindex: model not precached\n");
2991 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2994 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2995 static void VM_SV_particleeffectnum (void)
2998 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2999 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
3002 PRVM_G_FLOAT(OFS_RETURN) = i;
3005 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3006 static void VM_SV_trailparticles (void)
3008 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
3010 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3013 MSG_WriteByte(&sv.datagram, svc_trailparticles);
3014 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
3015 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
3016 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
3017 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
3018 SV_FlushBroadcastMessages();
3021 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
3022 static void VM_SV_pointparticles (void)
3024 int effectnum, count;
3026 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
3028 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3031 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
3032 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
3033 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
3034 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
3035 if (count == 1 && !VectorLength2(vel))
3038 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
3039 MSG_WriteShort(&sv.datagram, effectnum);
3040 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3044 // 1+2+12+12+2=29 bytes
3045 MSG_WriteByte(&sv.datagram, svc_pointparticles);
3046 MSG_WriteShort(&sv.datagram, effectnum);
3047 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3048 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
3049 MSG_WriteShort(&sv.datagram, count);
3052 SV_FlushBroadcastMessages();
3055 //PF_setpause, // void(float pause) setpause = #531;
3056 static void VM_SV_setpause(void) {
3058 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
3059 if (pauseValue != 0) { //pause the game
3061 sv.pausedstart = Sys_DoubleTime();
3062 } else { //disable pause, in case it was enabled
3063 if (sv.paused != 0) {
3068 // send notification to all clients
3069 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
3070 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
3073 prvm_builtin_t vm_sv_builtins[] = {
3074 NULL, // #0 NULL function (not callable) (QUAKE)
3075 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3076 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3077 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3078 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3079 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3080 VM_break, // #6 void() break (QUAKE)
3081 VM_random, // #7 float() random (QUAKE)
3082 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3083 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3084 VM_error, // #10 void(string e) error (QUAKE)
3085 VM_objerror, // #11 void(string e) objerror (QUAKE)
3086 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3087 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3088 VM_spawn, // #14 entity() spawn (QUAKE)
3089 VM_remove, // #15 void(entity e) remove (QUAKE)
3090 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3091 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3092 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3093 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3094 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3095 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3096 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3097 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3098 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3099 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3100 VM_ftos, // #26 string(float f) ftos (QUAKE)
3101 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3102 VM_coredump, // #28 void() coredump (QUAKE)
3103 VM_traceon, // #29 void() traceon (QUAKE)
3104 VM_traceoff, // #30 void() traceoff (QUAKE)
3105 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3106 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3107 NULL, // #33 (QUAKE)
3108 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3109 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3110 VM_rint, // #36 float(float v) rint (QUAKE)
3111 VM_floor, // #37 float(float v) floor (QUAKE)
3112 VM_ceil, // #38 float(float v) ceil (QUAKE)
3113 NULL, // #39 (QUAKE)
3114 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3115 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3116 NULL, // #42 (QUAKE)
3117 VM_fabs, // #43 float(float f) fabs (QUAKE)
3118 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3119 VM_cvar, // #45 float(string s) cvar (QUAKE)
3120 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3121 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3122 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3123 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3124 NULL, // #50 (QUAKE)
3125 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3126 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3127 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3128 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3129 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3130 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3131 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3132 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3133 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3134 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3135 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3136 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3137 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3138 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3139 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3140 NULL, // #66 (QUAKE)
3141 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3142 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3143 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3144 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3145 NULL, // #71 (QUAKE)
3146 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3147 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3148 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3149 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3150 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3151 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3152 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3153 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3154 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3155 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3156 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3157 NULL, // #83 (QUAKE)
3158 NULL, // #84 (QUAKE)
3159 NULL, // #85 (QUAKE)
3160 NULL, // #86 (QUAKE)
3161 NULL, // #87 (QUAKE)
3162 NULL, // #88 (QUAKE)
3163 NULL, // #89 (QUAKE)
3164 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3165 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3166 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3167 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3168 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3169 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3170 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3171 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3172 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3173 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3174 // FrikaC and Telejano range #100-#199
3185 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3186 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3187 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3188 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3189 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3190 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3191 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3192 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3193 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3194 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3275 // FTEQW range #200-#299
3294 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3297 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3298 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3299 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3300 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3301 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3302 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3303 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3304 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3305 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3306 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3308 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3316 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3376 // CSQC range #300-#399
3377 NULL, // #300 void() clearscene (EXT_CSQC)
3378 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3379 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3380 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3381 NULL, // #304 void() renderscene (EXT_CSQC)
3382 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3383 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3384 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3385 NULL, // #308 void() R_EndPolygon
3387 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3388 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3392 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3393 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3394 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3395 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3396 NULL, // #319 void(string name) freepic (EXT_CSQC)
3397 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3398 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3399 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3400 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3401 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3402 NULL, // #325 void(void) drawresetcliparea
3407 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3408 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3409 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3410 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3411 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3412 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3413 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3414 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3415 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3416 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3417 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3418 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3419 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3420 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3421 NULL, // #344 vector() getmousepos (EXT_CSQC)
3422 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3423 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3424 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3425 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3426 NULL, // #349 float() isdemo (EXT_CSQC)
3427 VM_isserver, // #350 float() isserver (EXT_CSQC)
3428 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3429 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3430 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3431 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3437 NULL, // #360 float() readbyte (EXT_CSQC)
3438 NULL, // #361 float() readchar (EXT_CSQC)
3439 NULL, // #362 float() readshort (EXT_CSQC)
3440 NULL, // #363 float() readlong (EXT_CSQC)
3441 NULL, // #364 float() readcoord (EXT_CSQC)
3442 NULL, // #365 float() readangle (EXT_CSQC)
3443 NULL, // #366 string() readstring (EXT_CSQC)
3444 NULL, // #367 float() readfloat (EXT_CSQC)
3477 // LordHavoc's range #400-#499
3478 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3479 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3480 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3481 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3482 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3483 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3484 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3485 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3486 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)
3487 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3488 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3489 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3490 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3491 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3492 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3493 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3494 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3495 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3496 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3497 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3498 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3499 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3500 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3501 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3502 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3503 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3504 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3505 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3506 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3507 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3508 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3509 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3510 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3511 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3512 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3513 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3514 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3515 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3516 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3517 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3518 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3519 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3520 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3521 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3522 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3523 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3524 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3525 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3526 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3527 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3528 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3529 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3530 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3531 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3532 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3533 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3534 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3535 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3537 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3538 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3539 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3540 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3541 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3542 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3543 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3544 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3545 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3546 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3547 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3549 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3550 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3551 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3552 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3553 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3554 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3555 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3556 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3557 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3558 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3559 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3560 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3561 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3562 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3563 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3564 VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3572 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3573 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3574 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3575 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3576 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3577 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3578 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3579 VM_SV_WritePicture, // #501
3581 VM_whichpack, // #503 string(string) whichpack = #503;
3588 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3589 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3590 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3591 VM_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET)
3592 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3593 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3594 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3595 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3596 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3597 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3609 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3702 VM_getextresponse, // #624 string getextresponse(void)
3706 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3708 void VM_SV_Cmd_Init(void)
3713 void VM_SV_Cmd_Reset(void)
3715 World_End(&sv.world);
3716 if(prog->funcoffsets.SV_Shutdown)
3718 func_t s = prog->funcoffsets.SV_Shutdown;
3719 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3720 PRVM_ExecuteProgram(s,"SV_Shutdown() required");