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 "
76 "DP_QC_EXTRESPONSEPACKET "
78 "DP_QC_FINDCHAIN_TOFIELD "
79 "DP_QC_FINDCHAINFLAGS "
80 "DP_QC_FINDCHAINFLOAT "
86 "DP_QC_GETSURFACEPOINTATTRIBUTE "
88 "DP_QC_GETTAGINFO_BONEPROPERTIES "
90 "DP_QC_GETTIME_CDTRACK "
92 "DP_QC_MULTIPLETEMPSTRINGS "
93 "DP_QC_NUM_FOR_EDICT "
95 "DP_QC_SINCOSSQRTPOW "
97 "DP_QC_STRINGBUFFERS "
98 "DP_QC_STRINGBUFFERS_CVARLIST "
99 "DP_QC_STRINGCOLORFUNCTIONS "
100 "DP_QC_STRING_CASE_FUNCTIONS "
102 "DP_QC_TOKENIZEBYSEPARATOR "
103 "DP_QC_TOKENIZE_CONSOLE "
106 "DP_QC_TRACE_MOVETYPE_HITMODEL "
107 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
108 "DP_QC_UNLIMITEDTEMPSTRINGS "
111 "DP_QC_VECTOANGLES_WITH_ROLL "
112 "DP_QC_VECTORVECTORS "
119 "DP_SND_DIRECTIONLESSATTNNONE "
126 "DP_SV_BOUNCEFACTOR "
127 "DP_SV_CLIENTCOLORS "
130 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
131 "DP_SV_DRAWONLYTOCLIENT "
134 "DP_SV_ENTITYCONTENTSTRANSITION "
135 "DP_SV_MODELFLAGS_AS_EFFECTS "
136 "DP_SV_MOVETYPESTEP_LANDEVENT "
138 "DP_SV_NODRAWTOCLIENT "
139 "DP_SV_ONENTITYNOSPAWNFUNCTION "
140 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
142 "DP_SV_PLAYERPHYSICS "
143 "DP_SV_POINTPARTICLES "
145 "DP_SV_PRECACHEANYTIME "
149 "DP_SV_ROTATINGBMODEL "
153 "DP_SV_SPAWNFUNC_PREFIX "
154 "DP_SV_WRITEPICTURE "
155 "DP_SV_WRITEUNTERMINATEDSTRING "
159 "DP_TE_EXPLOSIONRGB "
161 "DP_TE_PARTICLECUBE "
162 "DP_TE_PARTICLERAIN "
163 "DP_TE_PARTICLESNOW "
165 "DP_TE_QUADEFFECTS1 "
168 "DP_TE_STANDARDEFFECTBUILTINS "
169 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
171 "DP_LIGHTSTYLE_STATICVALUE "
176 "KRIMZON_SV_PARSECLIENTCOMMAND "
179 "NEXUIZ_PLAYERMODEL "
181 "PRYDON_CLIENTCURSOR "
182 "TENEBRAE_GFX_DLIGHTS "
185 "DP_CSQC_SPAWNPARTICLE "
186 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
187 "DP_CSQC_ENTITYNOCULL "
188 //"EXT_CSQC " // not ready yet
195 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.
197 setorigin (entity, origin)
200 static void VM_SV_setorigin (void)
205 VM_SAFEPARMCOUNT(2, VM_setorigin);
207 e = PRVM_G_EDICT(OFS_PARM0);
208 if (e == prog->edicts)
210 VM_Warning("setorigin: can not modify world entity\n");
213 if (e->priv.server->free)
215 VM_Warning("setorigin: can not modify free entity\n");
218 org = PRVM_G_VECTOR(OFS_PARM1);
219 VectorCopy (org, e->fields.server->origin);
223 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
224 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
228 for (i=0 ; i<3 ; i++)
230 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
232 // set derived values
233 VectorCopy (min, e->fields.server->mins);
234 VectorCopy (max, e->fields.server->maxs);
235 VectorSubtract (max, min, e->fields.server->size);
244 the size box is rotated by the current angle
245 LordHavoc: no it isn't...
247 setsize (entity, minvector, maxvector)
250 static void VM_SV_setsize (void)
255 VM_SAFEPARMCOUNT(3, VM_setsize);
257 e = PRVM_G_EDICT(OFS_PARM0);
258 if (e == prog->edicts)
260 VM_Warning("setsize: can not modify world entity\n");
263 if (e->priv.server->free)
265 VM_Warning("setsize: can not modify free entity\n");
268 min = PRVM_G_VECTOR(OFS_PARM1);
269 max = PRVM_G_VECTOR(OFS_PARM2);
270 SetMinMaxSize (e, min, max, false);
278 setmodel(entity, model)
281 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
282 static void VM_SV_setmodel (void)
288 VM_SAFEPARMCOUNT(2, VM_setmodel);
290 e = PRVM_G_EDICT(OFS_PARM0);
291 if (e == prog->edicts)
293 VM_Warning("setmodel: can not modify world entity\n");
296 if (e->priv.server->free)
298 VM_Warning("setmodel: can not modify free entity\n");
301 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
302 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
303 e->fields.server->modelindex = i;
309 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
310 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
312 SetMinMaxSize (e, quakemins, quakemaxs, true);
315 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
322 single print to a specific client
324 sprint(clientent, value)
327 static void VM_SV_sprint (void)
331 char string[VM_STRINGTEMP_LENGTH];
333 VM_VarString(1, string, sizeof(string));
335 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
337 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
338 // LordHavoc: div0 requested that sprintto world operate like print
345 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
347 VM_Warning("tried to centerprint to a non-client\n");
351 client = svs.clients + entnum-1;
352 if (!client->netconnection)
355 MSG_WriteChar(&client->netconnection->message,svc_print);
356 MSG_WriteString(&client->netconnection->message, string);
364 single print to a specific client
366 centerprint(clientent, value)
369 static void VM_SV_centerprint (void)
373 char string[VM_STRINGTEMP_LENGTH];
375 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
377 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
379 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
381 VM_Warning("tried to centerprint to a non-client\n");
385 client = svs.clients + entnum-1;
386 if (!client->netconnection)
389 VM_VarString(1, string, sizeof(string));
390 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
391 MSG_WriteString(&client->netconnection->message, string);
398 particle(origin, color, count)
401 static void VM_SV_particle (void)
407 VM_SAFEPARMCOUNT(4, VM_SV_particle);
409 org = PRVM_G_VECTOR(OFS_PARM0);
410 dir = PRVM_G_VECTOR(OFS_PARM1);
411 color = PRVM_G_FLOAT(OFS_PARM2);
412 count = PRVM_G_FLOAT(OFS_PARM3);
413 SV_StartParticle (org, dir, (int)color, (int)count);
423 static void VM_SV_ambientsound (void)
427 float vol, attenuation;
430 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
432 pos = PRVM_G_VECTOR (OFS_PARM0);
433 samp = PRVM_G_STRING(OFS_PARM1);
434 vol = PRVM_G_FLOAT(OFS_PARM2);
435 attenuation = PRVM_G_FLOAT(OFS_PARM3);
437 // check to see if samp was properly precached
438 soundnum = SV_SoundIndex(samp, 1);
446 // add an svc_spawnambient command to the level signon packet
449 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
451 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
453 MSG_WriteVector(&sv.signon, pos, sv.protocol);
455 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
456 MSG_WriteShort (&sv.signon, soundnum);
458 MSG_WriteByte (&sv.signon, soundnum);
460 MSG_WriteByte (&sv.signon, (int)(vol*255));
461 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
469 Each entity can have eight independant sound sources, like voice,
472 Channel 0 is an auto-allocate channel, the others override anything
473 already running on that entity/channel pair.
475 An attenuation of 0 will play full volume everywhere in the level.
476 Larger attenuations will drop off.
480 static void VM_SV_sound (void)
484 prvm_edict_t *entity;
488 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
490 entity = PRVM_G_EDICT(OFS_PARM0);
491 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
492 sample = PRVM_G_STRING(OFS_PARM2);
493 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
494 attenuation = PRVM_G_FLOAT(OFS_PARM4);
497 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
501 if (volume < 0 || volume > 255)
503 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
507 if (attenuation < 0 || attenuation > 4)
509 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
513 if (channel < 0 || channel > 7)
515 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
519 SV_StartSound (entity, channel, sample, volume, attenuation);
526 Follows the same logic as VM_SV_sound, except instead of
527 an entity, an origin for the sound is provided, and channel
528 is omitted (since no entity is being tracked).
532 static void VM_SV_pointsound(void)
539 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
541 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
542 sample = PRVM_G_STRING(OFS_PARM1);
543 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
544 attenuation = PRVM_G_FLOAT(OFS_PARM3);
546 if (volume < 0 || volume > 255)
548 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
552 if (attenuation < 0 || attenuation > 4)
554 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
558 SV_StartPointSound (org, sample, volume, attenuation);
565 Used for use tracing and shot targeting
566 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
567 if the tryents flag is set.
569 traceline (vector1, vector2, movetype, ignore)
572 static void VM_SV_traceline (void)
579 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
581 prog->xfunction->builtinsprofile += 30;
583 v1 = PRVM_G_VECTOR(OFS_PARM0);
584 v2 = PRVM_G_VECTOR(OFS_PARM1);
585 move = (int)PRVM_G_FLOAT(OFS_PARM2);
586 ent = PRVM_G_EDICT(OFS_PARM3);
588 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]))
589 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));
591 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
593 VM_SetTraceGlobals(&trace);
601 Used for use tracing and shot targeting
602 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
603 if the tryents flag is set.
605 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
608 // LordHavoc: added this for my own use, VERY useful, similar to traceline
609 static void VM_SV_tracebox (void)
611 float *v1, *v2, *m1, *m2;
616 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
618 prog->xfunction->builtinsprofile += 30;
620 v1 = PRVM_G_VECTOR(OFS_PARM0);
621 m1 = PRVM_G_VECTOR(OFS_PARM1);
622 m2 = PRVM_G_VECTOR(OFS_PARM2);
623 v2 = PRVM_G_VECTOR(OFS_PARM3);
624 move = (int)PRVM_G_FLOAT(OFS_PARM4);
625 ent = PRVM_G_EDICT(OFS_PARM5);
627 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]))
628 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));
630 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
632 VM_SetTraceGlobals(&trace);
635 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
640 vec3_t original_origin;
641 vec3_t original_velocity;
642 vec3_t original_angles;
643 vec3_t original_avelocity;
647 VectorCopy(tossent->fields.server->origin , original_origin );
648 VectorCopy(tossent->fields.server->velocity , original_velocity );
649 VectorCopy(tossent->fields.server->angles , original_angles );
650 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
652 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
653 if (val != NULL && val->_float != 0)
654 gravity = val->_float;
657 gravity *= sv_gravity.value * 0.025;
659 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
661 SV_CheckVelocity (tossent);
662 tossent->fields.server->velocity[2] -= gravity;
663 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
664 VectorScale (tossent->fields.server->velocity, 0.05, move);
665 VectorAdd (tossent->fields.server->origin, move, end);
666 trace = SV_TraceBox(tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
667 VectorCopy (trace.endpos, tossent->fields.server->origin);
668 tossent->fields.server->velocity[2] -= gravity;
670 if (trace.fraction < 1)
674 VectorCopy(original_origin , tossent->fields.server->origin );
675 VectorCopy(original_velocity , tossent->fields.server->velocity );
676 VectorCopy(original_angles , tossent->fields.server->angles );
677 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
682 static void VM_SV_tracetoss (void)
686 prvm_edict_t *ignore;
688 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
690 prog->xfunction->builtinsprofile += 600;
692 ent = PRVM_G_EDICT(OFS_PARM0);
693 if (ent == prog->edicts)
695 VM_Warning("tracetoss: can not use world entity\n");
698 ignore = PRVM_G_EDICT(OFS_PARM1);
700 trace = SV_Trace_Toss (ent, ignore);
702 VM_SetTraceGlobals(&trace);
705 //============================================================================
707 static int checkpvsbytes;
708 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
710 static int VM_SV_newcheckclient (int check)
716 // cycle to the next one
718 check = bound(1, check, svs.maxclients);
719 if (check == svs.maxclients)
727 prog->xfunction->builtinsprofile++;
729 if (i == svs.maxclients+1)
731 // look up the client's edict
732 ent = PRVM_EDICT_NUM(i);
733 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
734 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
736 // found a valid client (possibly the same one again)
740 // get the PVS for the entity
741 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
743 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
744 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
753 Returns a client (or object that has a client enemy) that would be a
756 If there is more than one valid option, they are cycled each frame
758 If (self.origin + self.viewofs) is not in the PVS of the current target,
759 it is not returned at all.
764 int c_invis, c_notvis;
765 static void VM_SV_checkclient (void)
767 prvm_edict_t *ent, *self;
770 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
772 // find a new check if on a new frame
773 if (sv.time - sv.lastchecktime >= 0.1)
775 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
776 sv.lastchecktime = sv.time;
779 // return check if it might be visible
780 ent = PRVM_EDICT_NUM(sv.lastcheck);
781 if (ent->priv.server->free || ent->fields.server->health <= 0)
783 VM_RETURN_EDICT(prog->edicts);
787 // if current entity can't possibly see the check entity, return 0
788 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
789 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
790 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
793 VM_RETURN_EDICT(prog->edicts);
797 // might be able to see it
799 VM_RETURN_EDICT(ent);
802 //============================================================================
808 Checks if an entity is in a point's PVS.
809 Should be fast but can be inexact.
811 float checkpvs(vector viewpos, entity viewee) = #240;
814 static void VM_SV_checkpvs (void)
817 prvm_edict_t *viewee;
821 static int fatpvsbytes;
822 static unsigned char fatpvs[MAX_MAP_LEAFS/8];
825 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
826 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
827 viewee = PRVM_G_EDICT(OFS_PARM1);
829 if(viewee->priv.server->free)
831 VM_Warning("checkpvs: can not check free entity\n");
832 PRVM_G_FLOAT(OFS_RETURN) = 4;
837 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
839 // no PVS support on this worldmodel... darn
840 PRVM_G_FLOAT(OFS_RETURN) = 3;
843 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
846 // viewpos isn't in any PVS... darn
847 PRVM_G_FLOAT(OFS_RETURN) = 2;
850 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
852 // using fat PVS like FTEQW does (slow)
853 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
855 // no PVS support on this worldmodel... darn
856 PRVM_G_FLOAT(OFS_RETURN) = 3;
859 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
862 // viewpos isn't in any PVS... darn
863 PRVM_G_FLOAT(OFS_RETURN) = 2;
866 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
875 Sends text over to the client's execution buffer
877 stuffcmd (clientent, value, ...)
880 static void VM_SV_stuffcmd (void)
884 char string[VM_STRINGTEMP_LENGTH];
886 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
888 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
889 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
891 VM_Warning("Can't stuffcmd to a non-client\n");
895 VM_VarString(1, string, sizeof(string));
898 host_client = svs.clients + entnum-1;
899 Host_ClientCommands ("%s", string);
907 Returns a chain of entities that have origins within a spherical area
909 findradius (origin, radius)
912 static void VM_SV_findradius (void)
914 prvm_edict_t *ent, *chain;
915 vec_t radius, radius2;
916 vec3_t org, eorg, mins, maxs;
919 prvm_edict_t *touchedicts[MAX_EDICTS];
922 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
925 chainfield = PRVM_G_INT(OFS_PARM2);
927 chainfield = prog->fieldoffsets.chain;
929 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
931 chain = (prvm_edict_t *)prog->edicts;
933 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
934 radius = PRVM_G_FLOAT(OFS_PARM1);
935 radius2 = radius * radius;
937 mins[0] = org[0] - (radius + 1);
938 mins[1] = org[1] - (radius + 1);
939 mins[2] = org[2] - (radius + 1);
940 maxs[0] = org[0] + (radius + 1);
941 maxs[1] = org[1] + (radius + 1);
942 maxs[2] = org[2] + (radius + 1);
943 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
944 if (numtouchedicts > MAX_EDICTS)
946 // this never happens
947 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
948 numtouchedicts = MAX_EDICTS;
950 for (i = 0;i < numtouchedicts;i++)
952 ent = touchedicts[i];
953 prog->xfunction->builtinsprofile++;
954 // Quake did not return non-solid entities but darkplaces does
955 // (note: this is the reason you can't blow up fallen zombies)
956 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
958 // LordHavoc: compare against bounding box rather than center so it
959 // doesn't miss large objects, and use DotProduct instead of Length
960 // for a major speedup
961 VectorSubtract(org, ent->fields.server->origin, eorg);
962 if (sv_gameplayfix_findradiusdistancetobox.integer)
964 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
965 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
966 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
969 VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
970 if (DotProduct(eorg, eorg) < radius2)
972 PRVM_EDICTFIELDVALUE(ent,chainfield)->edict = PRVM_EDICT_TO_PROG(chain);
977 VM_RETURN_EDICT(chain);
980 static void VM_SV_precache_sound (void)
982 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
983 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
986 static void VM_SV_precache_model (void)
988 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
989 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
990 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
997 float(float yaw, float dist[, settrace]) walkmove
1000 static void VM_SV_walkmove (void)
1009 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1011 // assume failure if it returns early
1012 PRVM_G_FLOAT(OFS_RETURN) = 0;
1014 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1015 if (ent == prog->edicts)
1017 VM_Warning("walkmove: can not modify world entity\n");
1020 if (ent->priv.server->free)
1022 VM_Warning("walkmove: can not modify free entity\n");
1025 yaw = PRVM_G_FLOAT(OFS_PARM0);
1026 dist = PRVM_G_FLOAT(OFS_PARM1);
1027 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1029 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1032 yaw = yaw*M_PI*2 / 360;
1034 move[0] = cos(yaw)*dist;
1035 move[1] = sin(yaw)*dist;
1038 // save program state, because SV_movestep may call other progs
1039 oldf = prog->xfunction;
1040 oldself = prog->globals.server->self;
1042 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1045 // restore program state
1046 prog->xfunction = oldf;
1047 prog->globals.server->self = oldself;
1057 static void VM_SV_droptofloor (void)
1063 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1065 // assume failure if it returns early
1066 PRVM_G_FLOAT(OFS_RETURN) = 0;
1068 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1069 if (ent == prog->edicts)
1071 VM_Warning("droptofloor: can not modify world entity\n");
1074 if (ent->priv.server->free)
1076 VM_Warning("droptofloor: can not modify free entity\n");
1080 VectorCopy (ent->fields.server->origin, end);
1083 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1084 SV_UnstickEntity(ent);
1086 trace = SV_TraceBox(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1087 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1090 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]);
1091 VectorAdd(ent->fields.server->origin, offset, org);
1092 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1093 VectorSubtract(trace.endpos, offset, trace.endpos);
1094 if (trace.startsolid)
1096 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]);
1097 SV_UnstickEntity(ent);
1099 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1100 ent->fields.server->groundentity = 0;
1101 PRVM_G_FLOAT(OFS_RETURN) = 1;
1103 else if (trace.fraction < 1)
1105 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]);
1106 VectorCopy (trace.endpos, ent->fields.server->origin);
1107 SV_UnstickEntity(ent);
1109 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1110 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1111 PRVM_G_FLOAT(OFS_RETURN) = 1;
1112 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1113 ent->priv.server->suspendedinairflag = true;
1118 if (trace.fraction != 1)
1120 if (trace.fraction < 1)
1121 VectorCopy (trace.endpos, ent->fields.server->origin);
1123 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1124 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1125 PRVM_G_FLOAT(OFS_RETURN) = 1;
1126 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1127 ent->priv.server->suspendedinairflag = true;
1136 void(float style, string value) lightstyle
1139 static void VM_SV_lightstyle (void)
1146 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1148 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1149 val = PRVM_G_STRING(OFS_PARM1);
1151 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1152 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1155 // change the string in sv
1156 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1158 // send message to all clients on this server
1159 if (sv.state != ss_active)
1162 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1164 if (client->active && client->netconnection)
1166 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1167 MSG_WriteChar (&client->netconnection->message,style);
1168 MSG_WriteString (&client->netconnection->message, val);
1178 static void VM_SV_checkbottom (void)
1180 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1181 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1189 static void VM_SV_pointcontents (void)
1191 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1192 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1199 Pick a vector for the player to shoot along
1200 vector aim(entity, missilespeed)
1203 static void VM_SV_aim (void)
1205 prvm_edict_t *ent, *check, *bestent;
1206 vec3_t start, dir, end, bestdir;
1209 float dist, bestdist;
1212 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1214 // assume failure if it returns early
1215 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1216 // if sv_aim is so high it can't possibly accept anything, skip out early
1217 if (sv_aim.value >= 1)
1220 ent = PRVM_G_EDICT(OFS_PARM0);
1221 if (ent == prog->edicts)
1223 VM_Warning("aim: can not use world entity\n");
1226 if (ent->priv.server->free)
1228 VM_Warning("aim: can not use free entity\n");
1231 speed = PRVM_G_FLOAT(OFS_PARM1);
1233 VectorCopy (ent->fields.server->origin, start);
1236 // try sending a trace straight
1237 VectorCopy (prog->globals.server->v_forward, dir);
1238 VectorMA (start, 2048, dir, end);
1239 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1240 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1241 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1243 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1248 // try all possible entities
1249 VectorCopy (dir, bestdir);
1250 bestdist = sv_aim.value;
1253 check = PRVM_NEXT_EDICT(prog->edicts);
1254 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1256 prog->xfunction->builtinsprofile++;
1257 if (check->fields.server->takedamage != DAMAGE_AIM)
1261 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1262 continue; // don't aim at teammate
1263 for (j=0 ; j<3 ; j++)
1264 end[j] = check->fields.server->origin[j]
1265 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1266 VectorSubtract (end, start, dir);
1267 VectorNormalize (dir);
1268 dist = DotProduct (dir, prog->globals.server->v_forward);
1269 if (dist < bestdist)
1270 continue; // to far to turn
1271 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1272 if (tr.ent == check)
1273 { // can shoot at this one
1281 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1282 dist = DotProduct (dir, prog->globals.server->v_forward);
1283 VectorScale (prog->globals.server->v_forward, dist, end);
1285 VectorNormalize (end);
1286 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1290 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1295 ===============================================================================
1299 ===============================================================================
1302 #define MSG_BROADCAST 0 // unreliable to all
1303 #define MSG_ONE 1 // reliable to one (msg_entity)
1304 #define MSG_ALL 2 // reliable to all
1305 #define MSG_INIT 3 // write to the init string
1306 #define MSG_ENTITY 5
1308 sizebuf_t *WriteDest (void)
1314 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1318 return &sv.datagram;
1321 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1322 entnum = PRVM_NUM_FOR_EDICT(ent);
1323 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1325 VM_Warning ("WriteDest: tried to write to non-client\n");
1326 return &sv.reliable_datagram;
1329 return &svs.clients[entnum-1].netconnection->message;
1332 VM_Warning ("WriteDest: bad destination\n");
1334 return &sv.reliable_datagram;
1340 return sv.writeentitiestoclient_msg;
1346 static void VM_SV_WriteByte (void)
1348 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1349 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1352 static void VM_SV_WriteChar (void)
1354 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1355 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1358 static void VM_SV_WriteShort (void)
1360 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1361 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1364 static void VM_SV_WriteLong (void)
1366 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1367 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1370 static void VM_SV_WriteAngle (void)
1372 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1373 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1376 static void VM_SV_WriteCoord (void)
1378 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1379 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1382 static void VM_SV_WriteString (void)
1384 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1385 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1388 static void VM_SV_WriteUnterminatedString (void)
1390 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1391 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1395 static void VM_SV_WriteEntity (void)
1397 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1398 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1401 // writes a picture as at most size bytes of data
1403 // IMGNAME \0 SIZE(short) IMGDATA
1404 // if failed to read/compress:
1406 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1407 static void VM_SV_WritePicture (void)
1409 const char *imgname;
1413 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1415 imgname = PRVM_G_STRING(OFS_PARM1);
1416 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1420 MSG_WriteString(WriteDest(), imgname);
1421 if(Image_Compress(imgname, size, &buf, &size))
1424 MSG_WriteShort(WriteDest(), size);
1425 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1430 MSG_WriteShort(WriteDest(), 0);
1434 //////////////////////////////////////////////////////////
1436 static void VM_SV_makestatic (void)
1441 // allow 0 parameters due to an id1 qc bug in which this function is used
1442 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1443 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1445 if (prog->argc >= 1)
1446 ent = PRVM_G_EDICT(OFS_PARM0);
1448 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1449 if (ent == prog->edicts)
1451 VM_Warning("makestatic: can not modify world entity\n");
1454 if (ent->priv.server->free)
1456 VM_Warning("makestatic: can not modify free entity\n");
1461 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1466 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1467 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1468 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1470 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1472 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1473 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1474 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1478 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1479 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1480 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1483 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1484 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1485 for (i=0 ; i<3 ; i++)
1487 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1488 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1491 // throw the entity away now
1495 //=============================================================================
1502 static void VM_SV_setspawnparms (void)
1508 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1510 ent = PRVM_G_EDICT(OFS_PARM0);
1511 i = PRVM_NUM_FOR_EDICT(ent);
1512 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1514 Con_Print("tried to setspawnparms on a non-client\n");
1518 // copy spawn parms out of the client_t
1519 client = svs.clients + i-1;
1520 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1521 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1528 Returns a color vector indicating the lighting at the requested point.
1530 (Internal Operation note: actually measures the light beneath the point, just like
1531 the model lighting on the client)
1536 static void VM_SV_getlight (void)
1538 vec3_t ambientcolor, diffusecolor, diffusenormal;
1540 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1541 p = PRVM_G_VECTOR(OFS_PARM0);
1542 VectorClear(ambientcolor);
1543 VectorClear(diffusecolor);
1544 VectorClear(diffusenormal);
1545 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1546 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1547 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1552 unsigned char type; // 1/2/8 or other value if isn't used
1556 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1557 static int vm_customstats_last;
1559 void VM_CustomStats_Clear (void)
1563 Z_Free(vm_customstats);
1564 vm_customstats = NULL;
1565 vm_customstats_last = -1;
1569 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1577 for(i=0; i<vm_customstats_last+1 ;i++)
1579 if(!vm_customstats[i].type)
1581 switch(vm_customstats[i].type)
1583 //string as 16 bytes
1586 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1587 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1588 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1589 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1590 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1592 //float field sent as-is
1594 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1596 //integer value of float field
1598 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1606 // void(float index, float type, .void field) SV_AddStat = #232;
1607 // Set up an auto-sent player stat.
1608 // Client's get thier own fields sent to them. Index may not be less than 32.
1609 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1610 // 1: string (4 stats carrying a total of 16 charactures)
1611 // 2: float (one stat, float converted to an integer for transportation)
1612 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1613 static void VM_SV_AddStat (void)
1618 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1622 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1625 VM_Warning("PF_SV_AddStat: not enough memory\n");
1629 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1630 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1631 off = PRVM_G_INT (OFS_PARM2);
1636 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1639 if(i >= (MAX_CL_STATS-32))
1641 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1644 if(i > (MAX_CL_STATS-32-4) && type == 1)
1646 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1649 vm_customstats[i].type = type;
1650 vm_customstats[i].fieldoffset = off;
1651 if(vm_customstats_last < i)
1652 vm_customstats_last = i;
1659 copies data from one entity to another
1661 copyentity(src, dst)
1664 static void VM_SV_copyentity (void)
1666 prvm_edict_t *in, *out;
1667 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1668 in = PRVM_G_EDICT(OFS_PARM0);
1669 if (in == prog->edicts)
1671 VM_Warning("copyentity: can not read world entity\n");
1674 if (in->priv.server->free)
1676 VM_Warning("copyentity: can not read free entity\n");
1679 out = PRVM_G_EDICT(OFS_PARM1);
1680 if (out == prog->edicts)
1682 VM_Warning("copyentity: can not modify world entity\n");
1685 if (out->priv.server->free)
1687 VM_Warning("copyentity: can not modify free entity\n");
1690 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1699 sets the color of a client and broadcasts the update to all connected clients
1701 setcolor(clientent, value)
1704 static void VM_SV_setcolor (void)
1710 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1711 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1712 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1714 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1716 Con_Print("tried to setcolor a non-client\n");
1720 client = svs.clients + entnum-1;
1723 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1725 client->edict->fields.server->team = (i & 15) + 1;
1728 if (client->old_colors != client->colors)
1730 client->old_colors = client->colors;
1731 // send notification to all clients
1732 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1733 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1734 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1742 effect(origin, modelname, startframe, framecount, framerate)
1745 static void VM_SV_effect (void)
1749 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1750 s = PRVM_G_STRING(OFS_PARM1);
1753 VM_Warning("effect: no model specified\n");
1757 i = SV_ModelIndex(s, 1);
1760 VM_Warning("effect: model not precached\n");
1764 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1766 VM_Warning("effect: framecount < 1\n");
1770 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1772 VM_Warning("effect: framerate < 1\n");
1776 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));
1779 static void VM_SV_te_blood (void)
1781 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1782 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1784 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1785 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1787 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1788 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1789 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1791 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1792 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1793 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1795 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1796 SV_FlushBroadcastMessages();
1799 static void VM_SV_te_bloodshower (void)
1801 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1802 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1804 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1805 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1808 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1809 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1812 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1813 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1815 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1817 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1818 SV_FlushBroadcastMessages();
1821 static void VM_SV_te_explosionrgb (void)
1823 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1824 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1825 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1827 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1828 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1831 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1832 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1833 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1834 SV_FlushBroadcastMessages();
1837 static void VM_SV_te_particlecube (void)
1839 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1840 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1842 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1843 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1845 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1847 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1849 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1850 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1851 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1853 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1854 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1855 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1857 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1859 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1860 // gravity true/false
1861 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1863 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1864 SV_FlushBroadcastMessages();
1867 static void VM_SV_te_particlerain (void)
1869 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1870 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1872 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1873 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1875 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1876 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1877 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1879 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1880 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1881 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1883 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1884 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1885 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1887 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1889 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1890 SV_FlushBroadcastMessages();
1893 static void VM_SV_te_particlesnow (void)
1895 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1896 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1898 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1899 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1911 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1913 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1915 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1916 SV_FlushBroadcastMessages();
1919 static void VM_SV_te_spark (void)
1921 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1922 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1924 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1925 MSG_WriteByte(&sv.datagram, TE_SPARK);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1931 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1932 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1933 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1935 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1936 SV_FlushBroadcastMessages();
1939 static void VM_SV_te_gunshotquad (void)
1941 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1942 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1943 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1945 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1948 SV_FlushBroadcastMessages();
1951 static void VM_SV_te_spikequad (void)
1953 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1954 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1955 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1960 SV_FlushBroadcastMessages();
1963 static void VM_SV_te_superspikequad (void)
1965 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1966 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1967 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1970 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1972 SV_FlushBroadcastMessages();
1975 static void VM_SV_te_explosionquad (void)
1977 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
1978 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1979 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1983 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1984 SV_FlushBroadcastMessages();
1987 static void VM_SV_te_smallflash (void)
1989 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
1990 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1991 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1993 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1994 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1995 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1996 SV_FlushBroadcastMessages();
1999 static void VM_SV_te_customflash (void)
2001 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2002 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2004 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2005 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2007 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2008 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2009 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2011 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2013 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2015 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2016 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2017 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2018 SV_FlushBroadcastMessages();
2021 static void VM_SV_te_gunshot (void)
2023 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2024 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2025 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2028 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2029 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2030 SV_FlushBroadcastMessages();
2033 static void VM_SV_te_spike (void)
2035 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2036 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2037 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2039 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2040 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2041 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2042 SV_FlushBroadcastMessages();
2045 static void VM_SV_te_superspike (void)
2047 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2048 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2049 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2052 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2054 SV_FlushBroadcastMessages();
2057 static void VM_SV_te_explosion (void)
2059 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2060 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2061 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2063 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2064 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2065 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2066 SV_FlushBroadcastMessages();
2069 static void VM_SV_te_tarexplosion (void)
2071 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2072 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2073 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2075 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2076 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2077 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2078 SV_FlushBroadcastMessages();
2081 static void VM_SV_te_wizspike (void)
2083 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2084 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2085 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2087 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2088 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2089 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2090 SV_FlushBroadcastMessages();
2093 static void VM_SV_te_knightspike (void)
2095 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2096 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2097 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2099 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2100 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2101 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2102 SV_FlushBroadcastMessages();
2105 static void VM_SV_te_lavasplash (void)
2107 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2108 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2109 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2111 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2112 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2113 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2114 SV_FlushBroadcastMessages();
2117 static void VM_SV_te_teleport (void)
2119 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2120 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2121 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2123 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2124 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2125 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2126 SV_FlushBroadcastMessages();
2129 static void VM_SV_te_explosion2 (void)
2131 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2132 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2133 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2135 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2136 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2137 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2139 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2140 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2141 SV_FlushBroadcastMessages();
2144 static void VM_SV_te_lightning1 (void)
2146 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2147 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2148 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2150 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2152 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2153 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2154 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2156 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2157 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2158 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2159 SV_FlushBroadcastMessages();
2162 static void VM_SV_te_lightning2 (void)
2164 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2165 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2166 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2168 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2170 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2171 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2172 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2174 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2175 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2176 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2177 SV_FlushBroadcastMessages();
2180 static void VM_SV_te_lightning3 (void)
2182 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2183 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2184 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2186 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2188 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2189 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2190 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2192 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2193 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2194 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2195 SV_FlushBroadcastMessages();
2198 static void VM_SV_te_beam (void)
2200 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2201 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2202 MSG_WriteByte(&sv.datagram, TE_BEAM);
2204 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2206 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2207 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2208 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2210 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2211 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2212 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2213 SV_FlushBroadcastMessages();
2216 static void VM_SV_te_plasmaburn (void)
2218 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2219 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2220 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2221 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2222 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2223 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2224 SV_FlushBroadcastMessages();
2227 static void VM_SV_te_flamejet (void)
2229 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2230 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2231 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2234 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2235 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2237 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2238 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2239 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2241 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2242 SV_FlushBroadcastMessages();
2245 void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2248 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2250 bestdist = 1000000000;
2252 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2254 // clip original point to each triangle of the surface and find the
2255 // triangle that is closest
2256 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2257 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2258 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2259 TriangleNormal(v[0], v[1], v[2], facenormal);
2260 VectorNormalize(facenormal);
2261 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2262 VectorMA(p, offsetdist, facenormal, temp);
2263 for (j = 0, k = 2;j < 3;k = j, j++)
2265 VectorSubtract(v[k], v[j], edgenormal);
2266 CrossProduct(edgenormal, facenormal, sidenormal);
2267 VectorNormalize(sidenormal);
2268 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2270 VectorMA(temp, offsetdist, sidenormal, temp);
2272 dist = VectorDistance2(temp, p);
2273 if (bestdist > dist)
2276 VectorCopy(temp, out);
2281 static dp_model_t *getmodel(prvm_edict_t *ed)
2284 if (!ed || ed->priv.server->free)
2286 modelindex = (int)ed->fields.server->modelindex;
2287 if (modelindex < 1 || modelindex >= MAX_MODELS)
2289 return sv.models[modelindex];
2292 static msurface_t *getsurface(dp_model_t *model, int surfacenum)
2294 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2296 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2300 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2301 static void VM_SV_getsurfacenumpoints(void)
2304 msurface_t *surface;
2305 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints);
2306 // return 0 if no such surface
2307 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2309 PRVM_G_FLOAT(OFS_RETURN) = 0;
2313 // note: this (incorrectly) assumes it is a simple polygon
2314 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2316 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2317 static void VM_SV_getsurfacepoint(void)
2321 msurface_t *surface;
2323 VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint);
2324 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2325 ed = PRVM_G_EDICT(OFS_PARM0);
2326 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2328 // note: this (incorrectly) assumes it is a simple polygon
2329 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2330 if (pointnum < 0 || pointnum >= surface->num_vertices)
2332 // FIXME: implement rotation/scaling
2333 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2335 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
2336 // float SPA_POSITION = 0;
2337 // float SPA_S_AXIS = 1;
2338 // float SPA_T_AXIS = 2;
2339 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2340 // float SPA_TEXCOORDS0 = 4;
2341 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2342 // float SPA_LIGHTMAP0_COLOR = 6;
2343 static void VM_SV_getsurfacepointattribute(void)
2347 msurface_t *surface;
2351 VM_SAFEPARMCOUNT(4, VM_SV_getsurfacepoint);
2352 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2353 ed = PRVM_G_EDICT(OFS_PARM0);
2354 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2356 // note: this (incorrectly) assumes it is a simple polygon
2357 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2358 if (pointnum < 0 || pointnum >= surface->num_vertices)
2360 // FIXME: implement rotation/scaling
2361 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
2363 switch( attributetype ) {
2364 // float SPA_POSITION = 0;
2366 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2368 // float SPA_S_AXIS = 1;
2370 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2372 // float SPA_T_AXIS = 2;
2374 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2376 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2378 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2380 // float SPA_TEXCOORDS0 = 4;
2382 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2383 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
2384 ret[0] = texcoord[0];
2385 ret[1] = texcoord[1];
2389 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2391 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2392 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
2393 ret[0] = texcoord[0];
2394 ret[1] = texcoord[1];
2398 // float SPA_LIGHTMAP0_COLOR = 6;
2400 // ignore alpha for now..
2401 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2404 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2408 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2409 static void VM_SV_getsurfacenormal(void)
2412 msurface_t *surface;
2414 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal);
2415 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2416 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2418 // FIXME: implement rotation/scaling
2419 // note: this (incorrectly) assumes it is a simple polygon
2420 // note: this only returns the first triangle, so it doesn't work very
2421 // well for curved surfaces or arbitrary meshes
2422 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);
2423 VectorNormalize(normal);
2424 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2426 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2427 static void VM_SV_getsurfacetexture(void)
2430 msurface_t *surface;
2431 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture);
2432 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2433 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2435 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2437 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2438 static void VM_SV_getsurfacenearpoint(void)
2440 int surfacenum, best;
2442 vec_t dist, bestdist;
2445 msurface_t *surface;
2447 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint);
2448 PRVM_G_FLOAT(OFS_RETURN) = -1;
2449 ed = PRVM_G_EDICT(OFS_PARM0);
2450 point = PRVM_G_VECTOR(OFS_PARM1);
2452 if (!ed || ed->priv.server->free)
2454 model = getmodel(ed);
2455 if (!model || !model->num_surfaces)
2458 // FIXME: implement rotation/scaling
2459 VectorSubtract(point, ed->fields.server->origin, p);
2461 bestdist = 1000000000;
2462 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2464 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2465 // first see if the nearest point on the surface's box is closer than the previous match
2466 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2467 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2468 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2469 dist = VectorLength2(clipped);
2470 if (dist < bestdist)
2472 // it is, check the nearest point on the actual geometry
2473 clippointtosurface(model, surface, p, clipped);
2474 VectorSubtract(clipped, p, clipped);
2475 dist += VectorLength2(clipped);
2476 if (dist < bestdist)
2478 // that's closer too, store it as the best match
2484 PRVM_G_FLOAT(OFS_RETURN) = best;
2486 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2487 static void VM_SV_getsurfaceclippedpoint(void)
2491 msurface_t *surface;
2493 VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint);
2494 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2495 ed = PRVM_G_EDICT(OFS_PARM0);
2496 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2498 // FIXME: implement rotation/scaling
2499 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2500 clippointtosurface(model, surface, p, out);
2501 // FIXME: implement rotation/scaling
2502 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2505 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2506 //this function originally written by KrimZon, made shorter by LordHavoc
2507 static void VM_SV_clientcommand (void)
2509 client_t *temp_client;
2511 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2513 //find client for this entity
2514 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2515 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2517 Con_Print("PF_clientcommand: entity is not a client\n");
2521 temp_client = host_client;
2522 host_client = svs.clients + i;
2523 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2524 host_client = temp_client;
2527 //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)
2528 static void VM_SV_setattachment (void)
2530 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2531 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2532 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2536 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2538 if (e == prog->edicts)
2540 VM_Warning("setattachment: can not modify world entity\n");
2543 if (e->priv.server->free)
2545 VM_Warning("setattachment: can not modify free entity\n");
2549 if (tagentity == NULL)
2550 tagentity = prog->edicts;
2552 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2554 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2556 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2559 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2561 modelindex = (int)tagentity->fields.server->modelindex;
2562 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2564 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2566 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);
2569 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));
2573 /////////////////////////////////////////
2574 // DP_MD3_TAGINFO extension coded by VorteX
2576 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2581 i = (int)e->fields.server->modelindex;
2582 if (i < 1 || i >= MAX_MODELS)
2584 model = sv.models[i];
2586 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2589 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2598 Matrix4x4_CreateIdentity(tag_localmatrix);
2601 && (modelindex = (int)e->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2602 && (model = sv.models[(int)e->fields.server->modelindex])
2603 && model->animscenes)
2605 frame = (int)e->fields.server->frame;
2606 if (frame < 0 || frame >= model->numframes)
2609 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)e->fields.server->skin, model->animscenes[frame].firstframe, tagindex - 1, parentindex, tagname, tag_localmatrix);
2620 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2624 float pitchsign = 1;
2627 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2628 if (val && val->_float != 0)
2629 scale = val->_float;
2632 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);
2635 pitchsign = SV_GetPitchSign(ent);
2636 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);
2640 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2646 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2647 && (model = sv.models[(int)ent->fields.server->modelindex])
2648 && model->animscenes)
2650 // if model has wrong frame, engine automatically switches to model first frame
2651 frame = (int)ent->fields.server->frame;
2652 if (frame < 0 || frame >= model->numframes)
2654 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2656 *out = identitymatrix;
2660 // Warnings/errors code:
2661 // 0 - normal (everything all-right)
2664 // 3 - null or non-precached model
2665 // 4 - no tags with requested index
2666 // 5 - runaway loop at attachment chain
2667 extern cvar_t cl_bob;
2668 extern cvar_t cl_bobcycle;
2669 extern cvar_t cl_bobup;
2670 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2674 int modelindex, attachloop;
2675 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2678 *out = identitymatrix; // warnings and errors return identical matrix
2680 if (ent == prog->edicts)
2682 if (ent->priv.server->free)
2685 modelindex = (int)ent->fields.server->modelindex;
2686 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2689 model = sv.models[modelindex];
2691 tagmatrix = identitymatrix;
2692 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2696 if (attachloop >= 256) // prevent runaway looping
2698 // apply transformation by child's tagindex on parent entity and then
2699 // by parent entity itself
2700 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2701 if (ret && attachloop == 0)
2703 SV_GetEntityMatrix(ent, &entitymatrix, false);
2704 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2705 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2706 // next iteration we process the parent entity
2707 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2709 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2710 ent = PRVM_EDICT_NUM(val->edict);
2717 // RENDER_VIEWMODEL magic
2718 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2720 Matrix4x4_Copy(&tagmatrix, out);
2721 ent = PRVM_EDICT_NUM(val->edict);
2723 SV_GetEntityMatrix(ent, &entitymatrix, true);
2724 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2727 // Cl_bob, ported from rendering code
2728 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2731 // LordHavoc: this code is *weird*, but not replacable (I think it
2732 // should be done in QC on the server, but oh well, quake is quake)
2733 // LordHavoc: figured out bobup: the time at which the sin is at 180
2734 // degrees (which allows lengthening or squishing the peak or valley)
2735 cycle = sv.time/cl_bobcycle.value;
2736 cycle -= (int)cycle;
2737 if (cycle < cl_bobup.value)
2738 cycle = sin(M_PI * cycle / cl_bobup.value);
2740 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2741 // bob is proportional to velocity in the xy plane
2742 // (don't count Z, or jumping messes it up)
2743 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;
2744 bob = bob*0.3 + bob*0.7*cycle;
2745 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2752 //float(entity ent, string tagname) gettagindex;
2754 static void VM_SV_gettagindex (void)
2757 const char *tag_name;
2758 int modelindex, tag_index;
2760 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2762 ent = PRVM_G_EDICT(OFS_PARM0);
2763 tag_name = PRVM_G_STRING(OFS_PARM1);
2765 if (ent == prog->edicts)
2767 VM_Warning("gettagindex: can't affect world entity\n");
2770 if (ent->priv.server->free)
2772 VM_Warning("gettagindex: can't affect free entity\n");
2776 modelindex = (int)ent->fields.server->modelindex;
2778 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2779 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2782 tag_index = SV_GetTagIndex(ent, tag_name);
2784 if(developer.integer >= 100)
2785 Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2787 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2790 //vector(entity ent, float tagindex) gettaginfo;
2791 static void VM_SV_gettaginfo (void)
2795 matrix4x4_t tag_matrix;
2796 matrix4x4_t tag_localmatrix;
2798 const char *tagname;
2801 vec3_t fo, le, up, trans;
2803 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2805 e = PRVM_G_EDICT(OFS_PARM0);
2806 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2808 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2809 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, le, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2810 VectorScale(le, -1, prog->globals.server->v_right);
2811 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2812 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2814 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_parent)))
2815 val->_float = parentindex;
2816 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_name)))
2817 val->string = tagname ? PRVM_SetTempString(tagname) : 0;
2818 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_offset)))
2819 VectorCopy(trans, val->vector);
2820 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_forward)))
2821 VectorCopy(fo, val->vector);
2822 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_right)))
2823 VectorScale(le, -1, val->vector);
2824 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_up)))
2825 VectorCopy(up, val->vector);
2830 VM_Warning("gettagindex: can't affect world entity\n");
2833 VM_Warning("gettagindex: can't affect free entity\n");
2836 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2839 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2842 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2847 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2848 static void VM_SV_dropclient (void)
2851 client_t *oldhostclient;
2852 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2853 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2854 if (clientnum < 0 || clientnum >= svs.maxclients)
2856 VM_Warning("dropclient: not a client\n");
2859 if (!svs.clients[clientnum].active)
2861 VM_Warning("dropclient: that client slot is not connected\n");
2864 oldhostclient = host_client;
2865 host_client = svs.clients + clientnum;
2866 SV_DropClient(false);
2867 host_client = oldhostclient;
2870 //entity() spawnclient (DP_SV_BOTCLIENT)
2871 static void VM_SV_spawnclient (void)
2875 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2876 prog->xfunction->builtinsprofile += 2;
2878 for (i = 0;i < svs.maxclients;i++)
2880 if (!svs.clients[i].active)
2882 prog->xfunction->builtinsprofile += 100;
2883 SV_ConnectClient (i, NULL);
2884 // this has to be set or else ClientDisconnect won't be called
2885 // we assume the qc will call ClientConnect...
2886 svs.clients[i].clientconnectcalled = true;
2887 ed = PRVM_EDICT_NUM(i + 1);
2891 VM_RETURN_EDICT(ed);
2894 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2895 static void VM_SV_clienttype (void)
2898 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2899 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2900 if (clientnum < 0 || clientnum >= svs.maxclients)
2901 PRVM_G_FLOAT(OFS_RETURN) = 3;
2902 else if (!svs.clients[clientnum].active)
2903 PRVM_G_FLOAT(OFS_RETURN) = 0;
2904 else if (svs.clients[clientnum].netconnection)
2905 PRVM_G_FLOAT(OFS_RETURN) = 1;
2907 PRVM_G_FLOAT(OFS_RETURN) = 2;
2914 string(string key) serverkey
2917 void VM_SV_serverkey(void)
2919 char string[VM_STRINGTEMP_LENGTH];
2920 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2921 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2922 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2925 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2926 static void VM_SV_setmodelindex (void)
2931 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2933 e = PRVM_G_EDICT(OFS_PARM0);
2934 if (e == prog->edicts)
2936 VM_Warning("setmodelindex: can not modify world entity\n");
2939 if (e->priv.server->free)
2941 VM_Warning("setmodelindex: can not modify free entity\n");
2944 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2945 if (i <= 0 || i >= MAX_MODELS)
2947 VM_Warning("setmodelindex: invalid modelindex\n");
2950 if (!sv.model_precache[i][0])
2952 VM_Warning("setmodelindex: model not precached\n");
2956 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2957 e->fields.server->modelindex = i;
2963 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2964 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2966 SetMinMaxSize (e, quakemins, quakemaxs, true);
2969 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2972 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2973 static void VM_SV_modelnameforindex (void)
2976 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2978 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2980 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2981 if (i <= 0 || i >= MAX_MODELS)
2983 VM_Warning("modelnameforindex: invalid modelindex\n");
2986 if (!sv.model_precache[i][0])
2988 VM_Warning("modelnameforindex: model not precached\n");
2992 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2995 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2996 static void VM_SV_particleeffectnum (void)
2999 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
3000 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
3003 PRVM_G_FLOAT(OFS_RETURN) = i;
3006 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3007 static void VM_SV_trailparticles (void)
3009 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
3011 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3014 MSG_WriteByte(&sv.datagram, svc_trailparticles);
3015 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
3016 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
3017 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
3018 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
3019 SV_FlushBroadcastMessages();
3022 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
3023 static void VM_SV_pointparticles (void)
3025 int effectnum, count;
3027 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
3029 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3032 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
3033 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
3034 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
3035 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
3036 if (count == 1 && !VectorLength2(vel))
3039 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
3040 MSG_WriteShort(&sv.datagram, effectnum);
3041 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3045 // 1+2+12+12+2=29 bytes
3046 MSG_WriteByte(&sv.datagram, svc_pointparticles);
3047 MSG_WriteShort(&sv.datagram, effectnum);
3048 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3049 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
3050 MSG_WriteShort(&sv.datagram, count);
3053 SV_FlushBroadcastMessages();
3056 //PF_setpause, // void(float pause) setpause = #531;
3057 static void VM_SV_setpause(void) {
3059 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
3060 if (pauseValue != 0) { //pause the game
3062 sv.pausedstart = Sys_DoubleTime();
3063 } else { //disable pause, in case it was enabled
3064 if (sv.paused != 0) {
3069 // send notification to all clients
3070 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
3071 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
3074 prvm_builtin_t vm_sv_builtins[] = {
3075 NULL, // #0 NULL function (not callable) (QUAKE)
3076 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3077 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3078 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3079 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3080 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3081 VM_break, // #6 void() break (QUAKE)
3082 VM_random, // #7 float() random (QUAKE)
3083 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3084 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3085 VM_error, // #10 void(string e) error (QUAKE)
3086 VM_objerror, // #11 void(string e) objerror (QUAKE)
3087 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3088 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3089 VM_spawn, // #14 entity() spawn (QUAKE)
3090 VM_remove, // #15 void(entity e) remove (QUAKE)
3091 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3092 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3093 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3094 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3095 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3096 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3097 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3098 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3099 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3100 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3101 VM_ftos, // #26 string(float f) ftos (QUAKE)
3102 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3103 VM_coredump, // #28 void() coredump (QUAKE)
3104 VM_traceon, // #29 void() traceon (QUAKE)
3105 VM_traceoff, // #30 void() traceoff (QUAKE)
3106 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3107 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3108 NULL, // #33 (QUAKE)
3109 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3110 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3111 VM_rint, // #36 float(float v) rint (QUAKE)
3112 VM_floor, // #37 float(float v) floor (QUAKE)
3113 VM_ceil, // #38 float(float v) ceil (QUAKE)
3114 NULL, // #39 (QUAKE)
3115 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3116 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3117 NULL, // #42 (QUAKE)
3118 VM_fabs, // #43 float(float f) fabs (QUAKE)
3119 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3120 VM_cvar, // #45 float(string s) cvar (QUAKE)
3121 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3122 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3123 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3124 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3125 NULL, // #50 (QUAKE)
3126 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3127 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3128 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3129 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3130 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3131 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3132 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3133 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3134 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3135 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3136 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3137 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3138 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3139 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3140 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3141 NULL, // #66 (QUAKE)
3142 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3143 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3144 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3145 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3146 NULL, // #71 (QUAKE)
3147 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3148 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3149 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3150 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3151 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3152 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3153 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3154 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3155 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3156 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3157 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3158 NULL, // #83 (QUAKE)
3159 NULL, // #84 (QUAKE)
3160 NULL, // #85 (QUAKE)
3161 NULL, // #86 (QUAKE)
3162 NULL, // #87 (QUAKE)
3163 NULL, // #88 (QUAKE)
3164 NULL, // #89 (QUAKE)
3165 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3166 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3167 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3168 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3169 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3170 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3171 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3172 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3173 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3174 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3175 // FrikaC and Telejano range #100-#199
3186 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3187 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3188 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3189 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3190 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3191 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3192 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3193 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3194 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3195 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3276 // FTEQW range #200-#299
3295 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3298 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3299 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3300 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3301 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3302 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3303 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3304 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3305 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3306 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3307 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3309 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3317 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3377 // CSQC range #300-#399
3378 NULL, // #300 void() clearscene (EXT_CSQC)
3379 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3380 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3381 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3382 NULL, // #304 void() renderscene (EXT_CSQC)
3383 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3384 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3385 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3386 NULL, // #308 void() R_EndPolygon
3388 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3389 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3393 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3394 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3395 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3396 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3397 NULL, // #319 void(string name) freepic (EXT_CSQC)
3398 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3399 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3400 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3401 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3402 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3403 NULL, // #325 void(void) drawresetcliparea
3408 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3409 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3410 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3411 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3412 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3413 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3414 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3415 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3416 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3417 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3418 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3419 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3420 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3421 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3422 NULL, // #344 vector() getmousepos (EXT_CSQC)
3423 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3424 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3425 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3426 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3427 NULL, // #349 float() isdemo (EXT_CSQC)
3428 VM_isserver, // #350 float() isserver (EXT_CSQC)
3429 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3430 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3431 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3432 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3438 NULL, // #360 float() readbyte (EXT_CSQC)
3439 NULL, // #361 float() readchar (EXT_CSQC)
3440 NULL, // #362 float() readshort (EXT_CSQC)
3441 NULL, // #363 float() readlong (EXT_CSQC)
3442 NULL, // #364 float() readcoord (EXT_CSQC)
3443 NULL, // #365 float() readangle (EXT_CSQC)
3444 NULL, // #366 string() readstring (EXT_CSQC)
3445 NULL, // #367 float() readfloat (EXT_CSQC)
3478 // LordHavoc's range #400-#499
3479 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3480 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3481 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3482 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3483 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3484 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3485 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3486 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3487 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)
3488 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3489 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3490 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3491 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3492 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3493 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3494 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3495 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3496 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3497 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3498 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3499 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3500 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3501 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3502 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3503 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3504 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3505 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3506 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3507 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3508 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3509 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3510 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3511 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3512 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3513 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3514 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3515 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3516 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3517 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3518 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3519 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3520 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3521 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3522 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3523 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3524 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3525 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3526 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3527 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3528 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3529 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3530 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3531 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3532 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3533 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3534 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3535 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3536 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3538 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3539 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3540 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3541 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3542 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3543 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3544 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3545 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3546 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3547 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3548 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3550 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3551 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3552 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3553 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3554 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3555 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3556 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3557 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3558 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3559 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3560 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3561 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3562 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3563 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3564 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3565 VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3573 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3574 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3575 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3576 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3577 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3578 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3579 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3580 VM_SV_WritePicture, // #501
3582 VM_whichpack, // #503 string(string) whichpack = #503;
3589 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3590 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3591 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3592 VM_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET)
3593 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3594 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3595 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3596 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3597 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3598 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3608 VM_loadfromdata, // #529
3609 VM_loadfromfile, // #530
3610 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3684 VM_callfunction, // #605
3685 VM_writetofile, // #606
3686 VM_isfunction, // #607
3692 VM_parseentitydata, // #613
3703 VM_getextresponse, // #624 string getextresponse(void)
3707 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3709 void VM_SV_Cmd_Init(void)
3714 void VM_SV_Cmd_Reset(void)
3716 World_End(&sv.world);
3717 if(prog->funcoffsets.SV_Shutdown)
3719 func_t s = prog->funcoffsets.SV_Shutdown;
3720 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3721 PRVM_ExecuteProgram(s,"SV_Shutdown() required");