6 //============================================================================
11 char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
22 "DP_CSQC_MULTIFRAME_INTERPOLATION "
38 "DP_ENT_CUSTOMCOLORMAP "
39 "DP_ENT_EXTERIORMODELTOCLIENT "
42 "DP_ENT_LOWPRECISION "
46 "DP_GFX_EXTERNALTEXTURES "
47 "DP_GFX_EXTERNALTEXTURES_PERMAP "
49 "DP_GFX_QUAKE3MODELTAGS "
52 "DP_GFX_MODEL_INTERPOLATION "
54 "DP_HALFLIFE_MAP_CVAR "
60 "DP_MOVETYPEBOUNCEMISSILE "
63 "DP_QC_ASINACOSATANATAN2TAN "
68 "DP_QC_CVAR_DEFSTRING "
69 "DP_QC_CVAR_DESCRIPTION "
75 "DP_QC_EXTRESPONSEPACKET "
77 "DP_QC_FINDCHAIN_TOFIELD "
78 "DP_QC_FINDCHAINFLAGS "
79 "DP_QC_FINDCHAINFLOAT "
85 "DP_QC_GETSURFACEPOINTATTRIBUTE "
87 "DP_QC_GETTAGINFO_BONEPROPERTIES "
89 "DP_QC_GETTIME_CDTRACK "
91 "DP_QC_MULTIPLETEMPSTRINGS "
92 "DP_QC_NUM_FOR_EDICT "
94 "DP_QC_SINCOSSQRTPOW "
96 "DP_QC_STRINGBUFFERS "
97 "DP_QC_STRINGBUFFERS_CVARLIST "
98 "DP_QC_STRINGCOLORFUNCTIONS "
99 "DP_QC_STRING_CASE_FUNCTIONS "
101 "DP_QC_TOKENIZEBYSEPARATOR "
102 "DP_QC_TOKENIZE_CONSOLE "
105 "DP_QC_TRACE_MOVETYPE_HITMODEL "
106 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
107 "DP_QC_UNLIMITEDTEMPSTRINGS "
110 "DP_QC_VECTOANGLES_WITH_ROLL "
111 "DP_QC_VECTORVECTORS "
118 "DP_SND_DIRECTIONLESSATTNNONE "
125 "DP_SV_BOUNCEFACTOR "
126 "DP_SV_CLIENTCOLORS "
129 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
130 "DP_SV_DRAWONLYTOCLIENT "
133 "DP_SV_ENTITYCONTENTSTRANSITION "
134 "DP_SV_MODELFLAGS_AS_EFFECTS "
135 "DP_SV_MOVETYPESTEP_LANDEVENT "
137 "DP_SV_NODRAWTOCLIENT "
138 "DP_SV_ONENTITYNOSPAWNFUNCTION "
139 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
141 "DP_SV_PLAYERPHYSICS "
142 "DP_SV_POINTPARTICLES "
144 "DP_SV_PRECACHEANYTIME "
148 "DP_SV_ROTATINGBMODEL "
152 "DP_SV_SPAWNFUNC_PREFIX "
153 "DP_SV_WRITEPICTURE "
154 "DP_SV_WRITEUNTERMINATEDSTRING "
158 "DP_TE_EXPLOSIONRGB "
160 "DP_TE_PARTICLECUBE "
161 "DP_TE_PARTICLERAIN "
162 "DP_TE_PARTICLESNOW "
164 "DP_TE_QUADEFFECTS1 "
167 "DP_TE_STANDARDEFFECTBUILTINS "
168 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
174 "KRIMZON_SV_PARSECLIENTCOMMAND "
177 "NEXUIZ_PLAYERMODEL "
179 "PRYDON_CLIENTCURSOR "
180 "TENEBRAE_GFX_DLIGHTS "
183 "DP_CSQC_SPAWNPARTICLE "
184 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
185 "DP_CSQC_ENTITYNOCULL "
186 //"EXT_CSQC " // not ready yet
193 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.
195 setorigin (entity, origin)
198 static void VM_SV_setorigin (void)
203 VM_SAFEPARMCOUNT(2, VM_setorigin);
205 e = PRVM_G_EDICT(OFS_PARM0);
206 if (e == prog->edicts)
208 VM_Warning("setorigin: can not modify world entity\n");
211 if (e->priv.server->free)
213 VM_Warning("setorigin: can not modify free entity\n");
216 org = PRVM_G_VECTOR(OFS_PARM1);
217 VectorCopy (org, e->fields.server->origin);
221 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
222 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
226 for (i=0 ; i<3 ; i++)
228 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
230 // set derived values
231 VectorCopy (min, e->fields.server->mins);
232 VectorCopy (max, e->fields.server->maxs);
233 VectorSubtract (max, min, e->fields.server->size);
242 the size box is rotated by the current angle
243 LordHavoc: no it isn't...
245 setsize (entity, minvector, maxvector)
248 static void VM_SV_setsize (void)
253 VM_SAFEPARMCOUNT(3, VM_setsize);
255 e = PRVM_G_EDICT(OFS_PARM0);
256 if (e == prog->edicts)
258 VM_Warning("setsize: can not modify world entity\n");
261 if (e->priv.server->free)
263 VM_Warning("setsize: can not modify free entity\n");
266 min = PRVM_G_VECTOR(OFS_PARM1);
267 max = PRVM_G_VECTOR(OFS_PARM2);
268 SetMinMaxSize (e, min, max, false);
276 setmodel(entity, model)
279 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
280 static void VM_SV_setmodel (void)
286 VM_SAFEPARMCOUNT(2, VM_setmodel);
288 e = PRVM_G_EDICT(OFS_PARM0);
289 if (e == prog->edicts)
291 VM_Warning("setmodel: can not modify world entity\n");
294 if (e->priv.server->free)
296 VM_Warning("setmodel: can not modify free entity\n");
299 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
300 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
301 e->fields.server->modelindex = i;
307 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
308 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
310 SetMinMaxSize (e, quakemins, quakemaxs, true);
313 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
320 single print to a specific client
322 sprint(clientent, value)
325 static void VM_SV_sprint (void)
329 char string[VM_STRINGTEMP_LENGTH];
331 VM_VarString(1, string, sizeof(string));
333 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
335 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
336 // LordHavoc: div0 requested that sprintto world operate like print
343 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
345 VM_Warning("tried to centerprint to a non-client\n");
349 client = svs.clients + entnum-1;
350 if (!client->netconnection)
353 MSG_WriteChar(&client->netconnection->message,svc_print);
354 MSG_WriteString(&client->netconnection->message, string);
362 single print to a specific client
364 centerprint(clientent, value)
367 static void VM_SV_centerprint (void)
371 char string[VM_STRINGTEMP_LENGTH];
373 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
375 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
377 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
379 VM_Warning("tried to centerprint to a non-client\n");
383 client = svs.clients + entnum-1;
384 if (!client->netconnection)
387 VM_VarString(1, string, sizeof(string));
388 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
389 MSG_WriteString(&client->netconnection->message, string);
396 particle(origin, color, count)
399 static void VM_SV_particle (void)
405 VM_SAFEPARMCOUNT(4, VM_SV_particle);
407 org = PRVM_G_VECTOR(OFS_PARM0);
408 dir = PRVM_G_VECTOR(OFS_PARM1);
409 color = PRVM_G_FLOAT(OFS_PARM2);
410 count = PRVM_G_FLOAT(OFS_PARM3);
411 SV_StartParticle (org, dir, (int)color, (int)count);
421 static void VM_SV_ambientsound (void)
425 float vol, attenuation;
428 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
430 pos = PRVM_G_VECTOR (OFS_PARM0);
431 samp = PRVM_G_STRING(OFS_PARM1);
432 vol = PRVM_G_FLOAT(OFS_PARM2);
433 attenuation = PRVM_G_FLOAT(OFS_PARM3);
435 // check to see if samp was properly precached
436 soundnum = SV_SoundIndex(samp, 1);
444 // add an svc_spawnambient command to the level signon packet
447 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
449 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
451 MSG_WriteVector(&sv.signon, pos, sv.protocol);
453 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
454 MSG_WriteShort (&sv.signon, soundnum);
456 MSG_WriteByte (&sv.signon, soundnum);
458 MSG_WriteByte (&sv.signon, (int)(vol*255));
459 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
467 Each entity can have eight independant sound sources, like voice,
470 Channel 0 is an auto-allocate channel, the others override anything
471 already running on that entity/channel pair.
473 An attenuation of 0 will play full volume everywhere in the level.
474 Larger attenuations will drop off.
478 static void VM_SV_sound (void)
482 prvm_edict_t *entity;
486 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
488 entity = PRVM_G_EDICT(OFS_PARM0);
489 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
490 sample = PRVM_G_STRING(OFS_PARM2);
491 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
492 attenuation = PRVM_G_FLOAT(OFS_PARM4);
495 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
499 if (volume < 0 || volume > 255)
501 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
505 if (attenuation < 0 || attenuation > 4)
507 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
511 if (channel < 0 || channel > 7)
513 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
517 SV_StartSound (entity, channel, sample, volume, attenuation);
524 Follows the same logic as VM_SV_sound, except instead of
525 an entity, an origin for the sound is provided, and channel
526 is omitted (since no entity is being tracked).
530 static void VM_SV_pointsound(void)
537 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
539 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
540 sample = PRVM_G_STRING(OFS_PARM1);
541 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
542 attenuation = PRVM_G_FLOAT(OFS_PARM3);
544 if (volume < 0 || volume > 255)
546 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
550 if (attenuation < 0 || attenuation > 4)
552 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
556 SV_StartPointSound (org, sample, volume, attenuation);
563 Used for use tracing and shot targeting
564 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
565 if the tryents flag is set.
567 traceline (vector1, vector2, movetype, ignore)
570 static void VM_SV_traceline (void)
577 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
579 prog->xfunction->builtinsprofile += 30;
581 v1 = PRVM_G_VECTOR(OFS_PARM0);
582 v2 = PRVM_G_VECTOR(OFS_PARM1);
583 move = (int)PRVM_G_FLOAT(OFS_PARM2);
584 ent = PRVM_G_EDICT(OFS_PARM3);
586 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]))
587 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));
589 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
591 VM_SetTraceGlobals(&trace);
599 Used for use tracing and shot targeting
600 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
601 if the tryents flag is set.
603 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
606 // LordHavoc: added this for my own use, VERY useful, similar to traceline
607 static void VM_SV_tracebox (void)
609 float *v1, *v2, *m1, *m2;
614 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
616 prog->xfunction->builtinsprofile += 30;
618 v1 = PRVM_G_VECTOR(OFS_PARM0);
619 m1 = PRVM_G_VECTOR(OFS_PARM1);
620 m2 = PRVM_G_VECTOR(OFS_PARM2);
621 v2 = PRVM_G_VECTOR(OFS_PARM3);
622 move = (int)PRVM_G_FLOAT(OFS_PARM4);
623 ent = PRVM_G_EDICT(OFS_PARM5);
625 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]))
626 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));
628 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
630 VM_SetTraceGlobals(&trace);
633 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
638 vec3_t original_origin;
639 vec3_t original_velocity;
640 vec3_t original_angles;
641 vec3_t original_avelocity;
645 VectorCopy(tossent->fields.server->origin , original_origin );
646 VectorCopy(tossent->fields.server->velocity , original_velocity );
647 VectorCopy(tossent->fields.server->angles , original_angles );
648 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
650 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
651 if (val != NULL && val->_float != 0)
652 gravity = val->_float;
655 gravity *= sv_gravity.value * 0.025;
657 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
659 SV_CheckVelocity (tossent);
660 tossent->fields.server->velocity[2] -= gravity;
661 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
662 VectorScale (tossent->fields.server->velocity, 0.05, move);
663 VectorAdd (tossent->fields.server->origin, move, end);
664 trace = SV_TraceBox(tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
665 VectorCopy (trace.endpos, tossent->fields.server->origin);
666 tossent->fields.server->velocity[2] -= gravity;
668 if (trace.fraction < 1)
672 VectorCopy(original_origin , tossent->fields.server->origin );
673 VectorCopy(original_velocity , tossent->fields.server->velocity );
674 VectorCopy(original_angles , tossent->fields.server->angles );
675 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
680 static void VM_SV_tracetoss (void)
684 prvm_edict_t *ignore;
686 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
688 prog->xfunction->builtinsprofile += 600;
690 ent = PRVM_G_EDICT(OFS_PARM0);
691 if (ent == prog->edicts)
693 VM_Warning("tracetoss: can not use world entity\n");
696 ignore = PRVM_G_EDICT(OFS_PARM1);
698 trace = SV_Trace_Toss (ent, ignore);
700 VM_SetTraceGlobals(&trace);
703 //============================================================================
705 static int checkpvsbytes;
706 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
708 static int VM_SV_newcheckclient (int check)
714 // cycle to the next one
716 check = bound(1, check, svs.maxclients);
717 if (check == svs.maxclients)
725 prog->xfunction->builtinsprofile++;
727 if (i == svs.maxclients+1)
729 // look up the client's edict
730 ent = PRVM_EDICT_NUM(i);
731 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
732 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
734 // found a valid client (possibly the same one again)
738 // get the PVS for the entity
739 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
741 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
742 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
751 Returns a client (or object that has a client enemy) that would be a
754 If there is more than one valid option, they are cycled each frame
756 If (self.origin + self.viewofs) is not in the PVS of the current target,
757 it is not returned at all.
762 int c_invis, c_notvis;
763 static void VM_SV_checkclient (void)
765 prvm_edict_t *ent, *self;
768 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
770 // find a new check if on a new frame
771 if (sv.time - sv.lastchecktime >= 0.1)
773 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
774 sv.lastchecktime = sv.time;
777 // return check if it might be visible
778 ent = PRVM_EDICT_NUM(sv.lastcheck);
779 if (ent->priv.server->free || ent->fields.server->health <= 0)
781 VM_RETURN_EDICT(prog->edicts);
785 // if current entity can't possibly see the check entity, return 0
786 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
787 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
788 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
791 VM_RETURN_EDICT(prog->edicts);
795 // might be able to see it
797 VM_RETURN_EDICT(ent);
800 //============================================================================
806 Checks if an entity is in a point's PVS.
807 Should be fast but can be inexact.
809 float checkpvs(vector viewpos, entity viewee) = #240;
812 static void VM_SV_checkpvs (void)
815 prvm_edict_t *viewee;
819 static int fatpvsbytes;
820 static unsigned char fatpvs[MAX_MAP_LEAFS/8];
823 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
824 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
825 viewee = PRVM_G_EDICT(OFS_PARM1);
827 if(viewee->priv.server->free)
829 VM_Warning("checkpvs: can not check free entity\n");
830 PRVM_G_FLOAT(OFS_RETURN) = 4;
835 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
837 // no PVS support on this worldmodel... darn
838 PRVM_G_FLOAT(OFS_RETURN) = 3;
841 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
844 // viewpos isn't in any PVS... darn
845 PRVM_G_FLOAT(OFS_RETURN) = 2;
848 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
850 // using fat PVS like FTEQW does (slow)
851 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
853 // no PVS support on this worldmodel... darn
854 PRVM_G_FLOAT(OFS_RETURN) = 3;
857 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
860 // viewpos isn't in any PVS... darn
861 PRVM_G_FLOAT(OFS_RETURN) = 2;
864 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
873 Sends text over to the client's execution buffer
875 stuffcmd (clientent, value, ...)
878 static void VM_SV_stuffcmd (void)
882 char string[VM_STRINGTEMP_LENGTH];
884 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
886 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
887 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
889 VM_Warning("Can't stuffcmd to a non-client\n");
893 VM_VarString(1, string, sizeof(string));
896 host_client = svs.clients + entnum-1;
897 Host_ClientCommands ("%s", string);
905 Returns a chain of entities that have origins within a spherical area
907 findradius (origin, radius)
910 static void VM_SV_findradius (void)
912 prvm_edict_t *ent, *chain;
913 vec_t radius, radius2;
914 vec3_t org, eorg, mins, maxs;
917 prvm_edict_t *touchedicts[MAX_EDICTS];
920 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
923 chainfield = PRVM_G_INT(OFS_PARM2);
925 chainfield = prog->fieldoffsets.chain;
927 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
929 chain = (prvm_edict_t *)prog->edicts;
931 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
932 radius = PRVM_G_FLOAT(OFS_PARM1);
933 radius2 = radius * radius;
935 mins[0] = org[0] - (radius + 1);
936 mins[1] = org[1] - (radius + 1);
937 mins[2] = org[2] - (radius + 1);
938 maxs[0] = org[0] + (radius + 1);
939 maxs[1] = org[1] + (radius + 1);
940 maxs[2] = org[2] + (radius + 1);
941 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
942 if (numtouchedicts > MAX_EDICTS)
944 // this never happens
945 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
946 numtouchedicts = MAX_EDICTS;
948 for (i = 0;i < numtouchedicts;i++)
950 ent = touchedicts[i];
951 prog->xfunction->builtinsprofile++;
952 // Quake did not return non-solid entities but darkplaces does
953 // (note: this is the reason you can't blow up fallen zombies)
954 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
956 // LordHavoc: compare against bounding box rather than center so it
957 // doesn't miss large objects, and use DotProduct instead of Length
958 // for a major speedup
959 VectorSubtract(org, ent->fields.server->origin, eorg);
960 if (sv_gameplayfix_findradiusdistancetobox.integer)
962 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
963 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
964 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
967 VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
968 if (DotProduct(eorg, eorg) < radius2)
970 PRVM_EDICTFIELDVALUE(ent,chainfield)->edict = PRVM_EDICT_TO_PROG(chain);
975 VM_RETURN_EDICT(chain);
978 static void VM_SV_precache_sound (void)
980 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
981 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
984 static void VM_SV_precache_model (void)
986 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
987 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
988 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
995 float(float yaw, float dist[, settrace]) walkmove
998 static void VM_SV_walkmove (void)
1007 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1009 // assume failure if it returns early
1010 PRVM_G_FLOAT(OFS_RETURN) = 0;
1012 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1013 if (ent == prog->edicts)
1015 VM_Warning("walkmove: can not modify world entity\n");
1018 if (ent->priv.server->free)
1020 VM_Warning("walkmove: can not modify free entity\n");
1023 yaw = PRVM_G_FLOAT(OFS_PARM0);
1024 dist = PRVM_G_FLOAT(OFS_PARM1);
1025 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1027 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1030 yaw = yaw*M_PI*2 / 360;
1032 move[0] = cos(yaw)*dist;
1033 move[1] = sin(yaw)*dist;
1036 // save program state, because SV_movestep may call other progs
1037 oldf = prog->xfunction;
1038 oldself = prog->globals.server->self;
1040 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1043 // restore program state
1044 prog->xfunction = oldf;
1045 prog->globals.server->self = oldself;
1055 static void VM_SV_droptofloor (void)
1061 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1063 // assume failure if it returns early
1064 PRVM_G_FLOAT(OFS_RETURN) = 0;
1066 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1067 if (ent == prog->edicts)
1069 VM_Warning("droptofloor: can not modify world entity\n");
1072 if (ent->priv.server->free)
1074 VM_Warning("droptofloor: can not modify free entity\n");
1078 VectorCopy (ent->fields.server->origin, end);
1081 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1082 SV_UnstickEntity(ent);
1084 trace = SV_TraceBox(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1085 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1088 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]);
1089 VectorAdd(ent->fields.server->origin, offset, org);
1090 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1091 VectorSubtract(trace.endpos, offset, trace.endpos);
1092 if (trace.startsolid)
1094 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]);
1095 SV_UnstickEntity(ent);
1097 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1098 ent->fields.server->groundentity = 0;
1099 PRVM_G_FLOAT(OFS_RETURN) = 1;
1101 else if (trace.fraction < 1)
1103 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]);
1104 VectorCopy (trace.endpos, ent->fields.server->origin);
1105 SV_UnstickEntity(ent);
1107 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1108 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1109 PRVM_G_FLOAT(OFS_RETURN) = 1;
1110 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1111 ent->priv.server->suspendedinairflag = true;
1116 if (trace.fraction != 1)
1118 if (trace.fraction < 1)
1119 VectorCopy (trace.endpos, ent->fields.server->origin);
1121 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1122 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1123 PRVM_G_FLOAT(OFS_RETURN) = 1;
1124 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1125 ent->priv.server->suspendedinairflag = true;
1134 void(float style, string value) lightstyle
1137 static void VM_SV_lightstyle (void)
1144 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1146 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1147 val = PRVM_G_STRING(OFS_PARM1);
1149 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1150 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1153 // change the string in sv
1154 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1156 // send message to all clients on this server
1157 if (sv.state != ss_active)
1160 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1162 if (client->active && client->netconnection)
1164 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1165 MSG_WriteChar (&client->netconnection->message,style);
1166 MSG_WriteString (&client->netconnection->message, val);
1176 static void VM_SV_checkbottom (void)
1178 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1179 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1187 static void VM_SV_pointcontents (void)
1189 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1190 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1197 Pick a vector for the player to shoot along
1198 vector aim(entity, missilespeed)
1201 static void VM_SV_aim (void)
1203 prvm_edict_t *ent, *check, *bestent;
1204 vec3_t start, dir, end, bestdir;
1207 float dist, bestdist;
1210 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1212 // assume failure if it returns early
1213 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1214 // if sv_aim is so high it can't possibly accept anything, skip out early
1215 if (sv_aim.value >= 1)
1218 ent = PRVM_G_EDICT(OFS_PARM0);
1219 if (ent == prog->edicts)
1221 VM_Warning("aim: can not use world entity\n");
1224 if (ent->priv.server->free)
1226 VM_Warning("aim: can not use free entity\n");
1229 speed = PRVM_G_FLOAT(OFS_PARM1);
1231 VectorCopy (ent->fields.server->origin, start);
1234 // try sending a trace straight
1235 VectorCopy (prog->globals.server->v_forward, dir);
1236 VectorMA (start, 2048, dir, end);
1237 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1238 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1239 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1241 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1246 // try all possible entities
1247 VectorCopy (dir, bestdir);
1248 bestdist = sv_aim.value;
1251 check = PRVM_NEXT_EDICT(prog->edicts);
1252 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1254 prog->xfunction->builtinsprofile++;
1255 if (check->fields.server->takedamage != DAMAGE_AIM)
1259 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1260 continue; // don't aim at teammate
1261 for (j=0 ; j<3 ; j++)
1262 end[j] = check->fields.server->origin[j]
1263 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1264 VectorSubtract (end, start, dir);
1265 VectorNormalize (dir);
1266 dist = DotProduct (dir, prog->globals.server->v_forward);
1267 if (dist < bestdist)
1268 continue; // to far to turn
1269 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1270 if (tr.ent == check)
1271 { // can shoot at this one
1279 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1280 dist = DotProduct (dir, prog->globals.server->v_forward);
1281 VectorScale (prog->globals.server->v_forward, dist, end);
1283 VectorNormalize (end);
1284 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1288 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1293 ===============================================================================
1297 ===============================================================================
1300 #define MSG_BROADCAST 0 // unreliable to all
1301 #define MSG_ONE 1 // reliable to one (msg_entity)
1302 #define MSG_ALL 2 // reliable to all
1303 #define MSG_INIT 3 // write to the init string
1304 #define MSG_ENTITY 5
1306 sizebuf_t *WriteDest (void)
1312 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1316 return &sv.datagram;
1319 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1320 entnum = PRVM_NUM_FOR_EDICT(ent);
1321 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1323 VM_Warning ("WriteDest: tried to write to non-client\n");
1324 return &sv.reliable_datagram;
1327 return &svs.clients[entnum-1].netconnection->message;
1330 VM_Warning ("WriteDest: bad destination\n");
1332 return &sv.reliable_datagram;
1338 return sv.writeentitiestoclient_msg;
1344 static void VM_SV_WriteByte (void)
1346 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1347 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1350 static void VM_SV_WriteChar (void)
1352 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1353 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1356 static void VM_SV_WriteShort (void)
1358 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1359 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1362 static void VM_SV_WriteLong (void)
1364 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1365 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1368 static void VM_SV_WriteAngle (void)
1370 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1371 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1374 static void VM_SV_WriteCoord (void)
1376 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1377 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1380 static void VM_SV_WriteString (void)
1382 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1383 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1386 static void VM_SV_WriteUnterminatedString (void)
1388 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1389 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1392 static void VM_SV_WriteEntity (void)
1394 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1395 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1398 static void VM_SV_WriteByteINT (void)
1400 VM_SAFEPARMCOUNT(2, VM_SV_WriteByteINT);
1401 MSG_WriteByte (WriteDest(), PRVM_G_INT(OFS_PARM1));
1404 static void VM_SV_WriteCharINT (void)
1406 VM_SAFEPARMCOUNT(2, VM_SV_WriteCharINT);
1407 MSG_WriteChar (WriteDest(), PRVM_G_INT(OFS_PARM1));
1410 static void VM_SV_WriteShortINT (void)
1412 VM_SAFEPARMCOUNT(2, VM_SV_WriteShortINT);
1413 MSG_WriteShort (WriteDest(), PRVM_G_INT(OFS_PARM1));
1416 static void VM_SV_WriteLongINT (void)
1418 VM_SAFEPARMCOUNT(2, VM_SV_WriteLongINT);
1419 MSG_WriteLong (WriteDest(), PRVM_G_INT(OFS_PARM1));
1423 // writes a picture as at most size bytes of data
1425 // IMGNAME \0 SIZE(short) IMGDATA
1426 // if failed to read/compress:
1428 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1429 static void VM_SV_WritePicture (void)
1431 const char *imgname;
1435 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1437 imgname = PRVM_G_STRING(OFS_PARM1);
1438 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1442 MSG_WriteString(WriteDest(), imgname);
1443 if(Image_Compress(imgname, size, &buf, &size))
1446 MSG_WriteShort(WriteDest(), size);
1447 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1452 MSG_WriteShort(WriteDest(), 0);
1456 //////////////////////////////////////////////////////////
1458 static void VM_SV_makestatic (void)
1463 // allow 0 parameters due to an id1 qc bug in which this function is used
1464 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1465 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1467 if (prog->argc >= 1)
1468 ent = PRVM_G_EDICT(OFS_PARM0);
1470 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1471 if (ent == prog->edicts)
1473 VM_Warning("makestatic: can not modify world entity\n");
1476 if (ent->priv.server->free)
1478 VM_Warning("makestatic: can not modify free entity\n");
1483 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1488 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1489 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1490 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1492 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1494 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1495 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1496 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1500 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1501 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1502 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1505 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1506 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1507 for (i=0 ; i<3 ; i++)
1509 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1510 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1513 // throw the entity away now
1517 //=============================================================================
1524 static void VM_SV_setspawnparms (void)
1530 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1532 ent = PRVM_G_EDICT(OFS_PARM0);
1533 i = PRVM_NUM_FOR_EDICT(ent);
1534 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1536 Con_Print("tried to setspawnparms on a non-client\n");
1540 // copy spawn parms out of the client_t
1541 client = svs.clients + i-1;
1542 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1543 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1550 Returns a color vector indicating the lighting at the requested point.
1552 (Internal Operation note: actually measures the light beneath the point, just like
1553 the model lighting on the client)
1558 static void VM_SV_getlight (void)
1560 vec3_t ambientcolor, diffusecolor, diffusenormal;
1562 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1563 p = PRVM_G_VECTOR(OFS_PARM0);
1564 VectorClear(ambientcolor);
1565 VectorClear(diffusecolor);
1566 VectorClear(diffusenormal);
1567 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1568 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1569 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1574 unsigned char type; // 1/2/8 or other value if isn't used
1578 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1579 static int vm_customstats_last;
1581 void VM_CustomStats_Clear (void)
1585 Z_Free(vm_customstats);
1586 vm_customstats = NULL;
1587 vm_customstats_last = -1;
1591 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1599 for(i=0; i<vm_customstats_last+1 ;i++)
1601 if(!vm_customstats[i].type)
1603 switch(vm_customstats[i].type)
1605 //string as 16 bytes
1608 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1609 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1610 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1611 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1612 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1614 //float field sent as-is
1616 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1618 //integer value of float field
1620 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1628 // void(float index, float type, .void field) SV_AddStat = #232;
1629 // Set up an auto-sent player stat.
1630 // Client's get thier own fields sent to them. Index may not be less than 32.
1631 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1632 // 1: string (4 stats carrying a total of 16 charactures)
1633 // 2: float (one stat, float converted to an integer for transportation)
1634 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1635 static void VM_SV_AddStat (void)
1640 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1644 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1647 VM_Warning("PF_SV_AddStat: not enough memory\n");
1651 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1652 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1653 off = PRVM_G_INT (OFS_PARM2);
1658 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1661 if(i >= (MAX_CL_STATS-32))
1663 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1666 if(i > (MAX_CL_STATS-32-4) && type == 1)
1668 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1671 vm_customstats[i].type = type;
1672 vm_customstats[i].fieldoffset = off;
1673 if(vm_customstats_last < i)
1674 vm_customstats_last = i;
1681 copies data from one entity to another
1683 copyentity(src, dst)
1686 static void VM_SV_copyentity (void)
1688 prvm_edict_t *in, *out;
1689 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1690 in = PRVM_G_EDICT(OFS_PARM0);
1691 if (in == prog->edicts)
1693 VM_Warning("copyentity: can not read world entity\n");
1696 if (in->priv.server->free)
1698 VM_Warning("copyentity: can not read free entity\n");
1701 out = PRVM_G_EDICT(OFS_PARM1);
1702 if (out == prog->edicts)
1704 VM_Warning("copyentity: can not modify world entity\n");
1707 if (out->priv.server->free)
1709 VM_Warning("copyentity: can not modify free entity\n");
1712 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1721 sets the color of a client and broadcasts the update to all connected clients
1723 setcolor(clientent, value)
1726 static void VM_SV_setcolor (void)
1732 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1733 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1734 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1736 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1738 Con_Print("tried to setcolor a non-client\n");
1742 client = svs.clients + entnum-1;
1745 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1747 client->edict->fields.server->team = (i & 15) + 1;
1750 if (client->old_colors != client->colors)
1752 client->old_colors = client->colors;
1753 // send notification to all clients
1754 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1755 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1756 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1764 effect(origin, modelname, startframe, framecount, framerate)
1767 static void VM_SV_effect (void)
1771 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1772 s = PRVM_G_STRING(OFS_PARM1);
1775 VM_Warning("effect: no model specified\n");
1779 i = SV_ModelIndex(s, 1);
1782 VM_Warning("effect: model not precached\n");
1786 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1788 VM_Warning("effect: framecount < 1\n");
1792 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1794 VM_Warning("effect: framerate < 1\n");
1798 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));
1801 static void VM_SV_te_blood (void)
1803 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1804 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1806 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1807 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1809 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1810 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1813 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1814 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1815 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1817 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1818 SV_FlushBroadcastMessages();
1821 static void VM_SV_te_bloodshower (void)
1823 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1824 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1826 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1827 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1830 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1831 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1833 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1834 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1835 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1837 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1839 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1840 SV_FlushBroadcastMessages();
1843 static void VM_SV_te_explosionrgb (void)
1845 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1846 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1847 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1849 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1850 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1851 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1853 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1854 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1855 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1856 SV_FlushBroadcastMessages();
1859 static void VM_SV_te_particlecube (void)
1861 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1862 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1864 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1865 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1868 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1869 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1873 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1875 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1876 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1877 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1879 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1881 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1882 // gravity true/false
1883 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1885 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1886 SV_FlushBroadcastMessages();
1889 static void VM_SV_te_particlerain (void)
1891 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1892 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1894 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1895 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1909 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1911 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1912 SV_FlushBroadcastMessages();
1915 static void VM_SV_te_particlesnow (void)
1917 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1918 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1920 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1921 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1923 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1924 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1925 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1935 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1937 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1938 SV_FlushBroadcastMessages();
1941 static void VM_SV_te_spark (void)
1943 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1944 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1946 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1947 MSG_WriteByte(&sv.datagram, TE_SPARK);
1949 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1950 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1953 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1954 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1955 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1957 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1958 SV_FlushBroadcastMessages();
1961 static void VM_SV_te_gunshotquad (void)
1963 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1964 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1965 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1970 SV_FlushBroadcastMessages();
1973 static void VM_SV_te_spikequad (void)
1975 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1976 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1977 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1979 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1980 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1982 SV_FlushBroadcastMessages();
1985 static void VM_SV_te_superspikequad (void)
1987 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1988 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1989 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1991 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1992 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1993 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1994 SV_FlushBroadcastMessages();
1997 static void VM_SV_te_explosionquad (void)
1999 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2000 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2001 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2004 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2005 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2006 SV_FlushBroadcastMessages();
2009 static void VM_SV_te_smallflash (void)
2011 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2012 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2013 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2015 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2016 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2017 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2018 SV_FlushBroadcastMessages();
2021 static void VM_SV_te_customflash (void)
2023 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2024 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2026 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2027 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2029 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2030 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2031 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2033 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2035 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2037 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2038 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2039 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2040 SV_FlushBroadcastMessages();
2043 static void VM_SV_te_gunshot (void)
2045 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2046 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2047 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2049 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2050 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2052 SV_FlushBroadcastMessages();
2055 static void VM_SV_te_spike (void)
2057 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2058 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2059 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2061 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2062 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2063 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2064 SV_FlushBroadcastMessages();
2067 static void VM_SV_te_superspike (void)
2069 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2070 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2071 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2074 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2075 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2076 SV_FlushBroadcastMessages();
2079 static void VM_SV_te_explosion (void)
2081 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2082 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2083 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2085 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2086 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2087 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2088 SV_FlushBroadcastMessages();
2091 static void VM_SV_te_tarexplosion (void)
2093 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2094 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2095 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2097 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2098 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2099 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2100 SV_FlushBroadcastMessages();
2103 static void VM_SV_te_wizspike (void)
2105 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2106 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2107 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2109 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2110 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2111 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2112 SV_FlushBroadcastMessages();
2115 static void VM_SV_te_knightspike (void)
2117 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2118 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2119 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2121 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2122 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2123 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2124 SV_FlushBroadcastMessages();
2127 static void VM_SV_te_lavasplash (void)
2129 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2130 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2131 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2133 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2134 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2135 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2136 SV_FlushBroadcastMessages();
2139 static void VM_SV_te_teleport (void)
2141 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2142 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2143 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2145 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2146 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2147 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2148 SV_FlushBroadcastMessages();
2151 static void VM_SV_te_explosion2 (void)
2153 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2154 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2155 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2157 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2158 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2159 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2161 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2162 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2163 SV_FlushBroadcastMessages();
2166 static void VM_SV_te_lightning1 (void)
2168 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2169 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2170 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2172 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2174 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2175 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2176 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2178 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2179 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2180 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2181 SV_FlushBroadcastMessages();
2184 static void VM_SV_te_lightning2 (void)
2186 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2187 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2188 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2190 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2192 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2193 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2194 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2196 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2197 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2198 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2199 SV_FlushBroadcastMessages();
2202 static void VM_SV_te_lightning3 (void)
2204 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2205 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2206 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2208 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2210 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2211 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2212 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2214 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2215 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2216 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2217 SV_FlushBroadcastMessages();
2220 static void VM_SV_te_beam (void)
2222 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2223 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2224 MSG_WriteByte(&sv.datagram, TE_BEAM);
2226 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2230 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2232 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2234 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2235 SV_FlushBroadcastMessages();
2238 static void VM_SV_te_plasmaburn (void)
2240 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2241 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2242 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2243 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2244 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2245 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2246 SV_FlushBroadcastMessages();
2249 static void VM_SV_te_flamejet (void)
2251 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2252 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2253 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2255 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2256 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2257 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2259 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2260 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2261 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2263 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2264 SV_FlushBroadcastMessages();
2267 void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2270 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2272 bestdist = 1000000000;
2274 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2276 // clip original point to each triangle of the surface and find the
2277 // triangle that is closest
2278 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2279 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2280 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2281 TriangleNormal(v[0], v[1], v[2], facenormal);
2282 VectorNormalize(facenormal);
2283 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2284 VectorMA(p, offsetdist, facenormal, temp);
2285 for (j = 0, k = 2;j < 3;k = j, j++)
2287 VectorSubtract(v[k], v[j], edgenormal);
2288 CrossProduct(edgenormal, facenormal, sidenormal);
2289 VectorNormalize(sidenormal);
2290 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2292 VectorMA(temp, offsetdist, sidenormal, temp);
2294 dist = VectorDistance2(temp, p);
2295 if (bestdist > dist)
2298 VectorCopy(temp, out);
2303 static dp_model_t *getmodel(prvm_edict_t *ed)
2306 if (!ed || ed->priv.server->free)
2308 modelindex = (int)ed->fields.server->modelindex;
2309 if (modelindex < 1 || modelindex >= MAX_MODELS)
2311 return sv.models[modelindex];
2314 static msurface_t *getsurface(dp_model_t *model, int surfacenum)
2316 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2318 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2322 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2323 static void VM_SV_getsurfacenumpoints(void)
2326 msurface_t *surface;
2327 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints);
2328 // return 0 if no such surface
2329 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2331 PRVM_G_FLOAT(OFS_RETURN) = 0;
2335 // note: this (incorrectly) assumes it is a simple polygon
2336 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2338 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2339 static void VM_SV_getsurfacepoint(void)
2343 msurface_t *surface;
2345 VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint);
2346 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2347 ed = PRVM_G_EDICT(OFS_PARM0);
2348 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2350 // note: this (incorrectly) assumes it is a simple polygon
2351 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2352 if (pointnum < 0 || pointnum >= surface->num_vertices)
2354 // FIXME: implement rotation/scaling
2355 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2357 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
2358 // float SPA_POSITION = 0;
2359 // float SPA_S_AXIS = 1;
2360 // float SPA_T_AXIS = 2;
2361 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2362 // float SPA_TEXCOORDS0 = 4;
2363 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2364 // float SPA_LIGHTMAP0_COLOR = 6;
2365 static void VM_SV_getsurfacepointattribute(void)
2369 msurface_t *surface;
2373 VM_SAFEPARMCOUNT(4, VM_SV_getsurfacepoint);
2374 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2375 ed = PRVM_G_EDICT(OFS_PARM0);
2376 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2378 // note: this (incorrectly) assumes it is a simple polygon
2379 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2380 if (pointnum < 0 || pointnum >= surface->num_vertices)
2382 // FIXME: implement rotation/scaling
2383 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
2385 switch( attributetype ) {
2386 // float SPA_POSITION = 0;
2388 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2390 // float SPA_S_AXIS = 1;
2392 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2394 // float SPA_T_AXIS = 2;
2396 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2398 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2400 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2402 // float SPA_TEXCOORDS0 = 4;
2404 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2405 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
2406 ret[0] = texcoord[0];
2407 ret[1] = texcoord[1];
2411 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2413 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2414 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
2415 ret[0] = texcoord[0];
2416 ret[1] = texcoord[1];
2420 // float SPA_LIGHTMAP0_COLOR = 6;
2422 // ignore alpha for now..
2423 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2426 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2430 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2431 static void VM_SV_getsurfacenormal(void)
2434 msurface_t *surface;
2436 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal);
2437 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2438 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2440 // FIXME: implement rotation/scaling
2441 // note: this (incorrectly) assumes it is a simple polygon
2442 // note: this only returns the first triangle, so it doesn't work very
2443 // well for curved surfaces or arbitrary meshes
2444 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);
2445 VectorNormalize(normal);
2446 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2448 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2449 static void VM_SV_getsurfacetexture(void)
2452 msurface_t *surface;
2453 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture);
2454 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2455 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2457 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2459 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2460 static void VM_SV_getsurfacenearpoint(void)
2462 int surfacenum, best;
2464 vec_t dist, bestdist;
2467 msurface_t *surface;
2469 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint);
2470 PRVM_G_FLOAT(OFS_RETURN) = -1;
2471 ed = PRVM_G_EDICT(OFS_PARM0);
2472 point = PRVM_G_VECTOR(OFS_PARM1);
2474 if (!ed || ed->priv.server->free)
2476 model = getmodel(ed);
2477 if (!model || !model->num_surfaces)
2480 // FIXME: implement rotation/scaling
2481 VectorSubtract(point, ed->fields.server->origin, p);
2483 bestdist = 1000000000;
2484 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2486 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2487 // first see if the nearest point on the surface's box is closer than the previous match
2488 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2489 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2490 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2491 dist = VectorLength2(clipped);
2492 if (dist < bestdist)
2494 // it is, check the nearest point on the actual geometry
2495 clippointtosurface(model, surface, p, clipped);
2496 VectorSubtract(clipped, p, clipped);
2497 dist += VectorLength2(clipped);
2498 if (dist < bestdist)
2500 // that's closer too, store it as the best match
2506 PRVM_G_FLOAT(OFS_RETURN) = best;
2508 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2509 static void VM_SV_getsurfaceclippedpoint(void)
2513 msurface_t *surface;
2515 VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint);
2516 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2517 ed = PRVM_G_EDICT(OFS_PARM0);
2518 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2520 // FIXME: implement rotation/scaling
2521 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2522 clippointtosurface(model, surface, p, out);
2523 // FIXME: implement rotation/scaling
2524 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2527 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2528 //this function originally written by KrimZon, made shorter by LordHavoc
2529 static void VM_SV_clientcommand (void)
2531 client_t *temp_client;
2533 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2535 //find client for this entity
2536 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2537 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2539 Con_Print("PF_clientcommand: entity is not a client\n");
2543 temp_client = host_client;
2544 host_client = svs.clients + i;
2545 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2546 host_client = temp_client;
2549 //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)
2550 static void VM_SV_setattachment (void)
2552 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2553 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2554 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2558 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2560 if (e == prog->edicts)
2562 VM_Warning("setattachment: can not modify world entity\n");
2565 if (e->priv.server->free)
2567 VM_Warning("setattachment: can not modify free entity\n");
2571 if (tagentity == NULL)
2572 tagentity = prog->edicts;
2574 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2576 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2578 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2581 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2583 modelindex = (int)tagentity->fields.server->modelindex;
2584 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2586 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2588 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);
2591 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));
2595 /////////////////////////////////////////
2596 // DP_MD3_TAGINFO extension coded by VorteX
2598 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2603 i = (int)e->fields.server->modelindex;
2604 if (i < 1 || i >= MAX_MODELS)
2606 model = sv.models[i];
2608 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2611 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2620 Matrix4x4_CreateIdentity(tag_localmatrix);
2623 && (modelindex = (int)e->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2624 && (model = sv.models[(int)e->fields.server->modelindex])
2625 && model->animscenes)
2627 frame = (int)e->fields.server->frame;
2628 if (frame < 0 || frame >= model->numframes)
2631 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)e->fields.server->skin, model->animscenes[frame].firstframe, tagindex - 1, parentindex, tagname, tag_localmatrix);
2642 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2646 float pitchsign = 1;
2649 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2650 if (val && val->_float != 0)
2651 scale = val->_float;
2654 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);
2657 pitchsign = SV_GetPitchSign(ent);
2658 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);
2662 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2668 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2669 && (model = sv.models[(int)ent->fields.server->modelindex])
2670 && model->animscenes)
2672 // if model has wrong frame, engine automatically switches to model first frame
2673 frame = (int)ent->fields.server->frame;
2674 if (frame < 0 || frame >= model->numframes)
2676 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2678 *out = identitymatrix;
2682 // Warnings/errors code:
2683 // 0 - normal (everything all-right)
2686 // 3 - null or non-precached model
2687 // 4 - no tags with requested index
2688 // 5 - runaway loop at attachment chain
2689 extern cvar_t cl_bob;
2690 extern cvar_t cl_bobcycle;
2691 extern cvar_t cl_bobup;
2692 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2696 int modelindex, attachloop;
2697 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2700 *out = identitymatrix; // warnings and errors return identical matrix
2702 if (ent == prog->edicts)
2704 if (ent->priv.server->free)
2707 modelindex = (int)ent->fields.server->modelindex;
2708 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2711 model = sv.models[modelindex];
2713 tagmatrix = identitymatrix;
2714 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2718 if (attachloop >= 256) // prevent runaway looping
2720 // apply transformation by child's tagindex on parent entity and then
2721 // by parent entity itself
2722 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2723 if (ret && attachloop == 0)
2725 SV_GetEntityMatrix(ent, &entitymatrix, false);
2726 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2727 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2728 // next iteration we process the parent entity
2729 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2731 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2732 ent = PRVM_EDICT_NUM(val->edict);
2739 // RENDER_VIEWMODEL magic
2740 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2742 Matrix4x4_Copy(&tagmatrix, out);
2743 ent = PRVM_EDICT_NUM(val->edict);
2745 SV_GetEntityMatrix(ent, &entitymatrix, true);
2746 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2749 // Cl_bob, ported from rendering code
2750 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2753 // LordHavoc: this code is *weird*, but not replacable (I think it
2754 // should be done in QC on the server, but oh well, quake is quake)
2755 // LordHavoc: figured out bobup: the time at which the sin is at 180
2756 // degrees (which allows lengthening or squishing the peak or valley)
2757 cycle = sv.time/cl_bobcycle.value;
2758 cycle -= (int)cycle;
2759 if (cycle < cl_bobup.value)
2760 cycle = sin(M_PI * cycle / cl_bobup.value);
2762 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2763 // bob is proportional to velocity in the xy plane
2764 // (don't count Z, or jumping messes it up)
2765 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;
2766 bob = bob*0.3 + bob*0.7*cycle;
2767 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2774 //float(entity ent, string tagname) gettagindex;
2776 static void VM_SV_gettagindex (void)
2779 const char *tag_name;
2780 int modelindex, tag_index;
2782 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2784 ent = PRVM_G_EDICT(OFS_PARM0);
2785 tag_name = PRVM_G_STRING(OFS_PARM1);
2787 if (ent == prog->edicts)
2789 VM_Warning("gettagindex: can't affect world entity\n");
2792 if (ent->priv.server->free)
2794 VM_Warning("gettagindex: can't affect free entity\n");
2798 modelindex = (int)ent->fields.server->modelindex;
2800 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2801 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2804 tag_index = SV_GetTagIndex(ent, tag_name);
2806 if(developer.integer >= 100)
2807 Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2809 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2812 //vector(entity ent, float tagindex) gettaginfo;
2813 static void VM_SV_gettaginfo (void)
2817 matrix4x4_t tag_matrix;
2818 matrix4x4_t tag_localmatrix;
2820 const char *tagname;
2823 vec3_t fo, le, up, trans;
2825 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2827 e = PRVM_G_EDICT(OFS_PARM0);
2828 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2830 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2831 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, le, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2832 VectorScale(le, -1, prog->globals.server->v_right);
2833 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2834 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2836 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_parent)))
2837 val->_float = parentindex;
2838 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_name)))
2839 val->string = tagname ? PRVM_SetTempString(tagname) : 0;
2840 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_offset)))
2841 VectorCopy(trans, val->vector);
2842 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_forward)))
2843 VectorCopy(fo, val->vector);
2844 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_right)))
2845 VectorScale(le, -1, val->vector);
2846 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_up)))
2847 VectorCopy(up, val->vector);
2852 VM_Warning("gettagindex: can't affect world entity\n");
2855 VM_Warning("gettagindex: can't affect free entity\n");
2858 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2861 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2864 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2869 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2870 static void VM_SV_dropclient (void)
2873 client_t *oldhostclient;
2874 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2875 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2876 if (clientnum < 0 || clientnum >= svs.maxclients)
2878 VM_Warning("dropclient: not a client\n");
2881 if (!svs.clients[clientnum].active)
2883 VM_Warning("dropclient: that client slot is not connected\n");
2886 oldhostclient = host_client;
2887 host_client = svs.clients + clientnum;
2888 SV_DropClient(false);
2889 host_client = oldhostclient;
2892 //entity() spawnclient (DP_SV_BOTCLIENT)
2893 static void VM_SV_spawnclient (void)
2897 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2898 prog->xfunction->builtinsprofile += 2;
2900 for (i = 0;i < svs.maxclients;i++)
2902 if (!svs.clients[i].active)
2904 prog->xfunction->builtinsprofile += 100;
2905 SV_ConnectClient (i, NULL);
2906 // this has to be set or else ClientDisconnect won't be called
2907 // we assume the qc will call ClientConnect...
2908 svs.clients[i].clientconnectcalled = true;
2909 ed = PRVM_EDICT_NUM(i + 1);
2913 VM_RETURN_EDICT(ed);
2916 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2917 static void VM_SV_clienttype (void)
2920 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2921 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2922 if (clientnum < 0 || clientnum >= svs.maxclients)
2923 PRVM_G_FLOAT(OFS_RETURN) = 3;
2924 else if (!svs.clients[clientnum].active)
2925 PRVM_G_FLOAT(OFS_RETURN) = 0;
2926 else if (svs.clients[clientnum].netconnection)
2927 PRVM_G_FLOAT(OFS_RETURN) = 1;
2929 PRVM_G_FLOAT(OFS_RETURN) = 2;
2936 string(string key) serverkey
2939 void VM_SV_serverkey(void)
2941 char string[VM_STRINGTEMP_LENGTH];
2942 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2943 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2944 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2947 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2948 static void VM_SV_setmodelindex (void)
2953 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2955 e = PRVM_G_EDICT(OFS_PARM0);
2956 if (e == prog->edicts)
2958 VM_Warning("setmodelindex: can not modify world entity\n");
2961 if (e->priv.server->free)
2963 VM_Warning("setmodelindex: can not modify free entity\n");
2966 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2967 if (i <= 0 || i >= MAX_MODELS)
2969 VM_Warning("setmodelindex: invalid modelindex\n");
2972 if (!sv.model_precache[i][0])
2974 VM_Warning("setmodelindex: model not precached\n");
2978 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2979 e->fields.server->modelindex = i;
2985 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2986 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2988 SetMinMaxSize (e, quakemins, quakemaxs, true);
2991 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2994 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2995 static void VM_SV_modelnameforindex (void)
2998 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
3000 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
3002 i = (int)PRVM_G_FLOAT(OFS_PARM0);
3003 if (i <= 0 || i >= MAX_MODELS)
3005 VM_Warning("modelnameforindex: invalid modelindex\n");
3008 if (!sv.model_precache[i][0])
3010 VM_Warning("modelnameforindex: model not precached\n");
3014 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
3017 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
3018 static void VM_SV_particleeffectnum (void)
3021 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
3022 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
3025 PRVM_G_FLOAT(OFS_RETURN) = i;
3028 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3029 static void VM_SV_trailparticles (void)
3031 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
3033 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3036 MSG_WriteByte(&sv.datagram, svc_trailparticles);
3037 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
3038 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
3039 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
3040 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
3041 SV_FlushBroadcastMessages();
3044 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
3045 static void VM_SV_pointparticles (void)
3047 int effectnum, count;
3049 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
3051 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3054 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
3055 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
3056 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
3057 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
3058 if (count == 1 && !VectorLength2(vel))
3061 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
3062 MSG_WriteShort(&sv.datagram, effectnum);
3063 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3067 // 1+2+12+12+2=29 bytes
3068 MSG_WriteByte(&sv.datagram, svc_pointparticles);
3069 MSG_WriteShort(&sv.datagram, effectnum);
3070 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3071 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
3072 MSG_WriteShort(&sv.datagram, count);
3075 SV_FlushBroadcastMessages();
3078 //PF_setpause, // void(float pause) setpause = #531;
3079 static void VM_SV_setpause(void) {
3081 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
3082 if (pauseValue != 0) { //pause the game
3084 sv.pausedstart = Sys_DoubleTime();
3085 } else { //disable pause, in case it was enabled
3086 if (sv.paused != 0) {
3091 // send notification to all clients
3092 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
3093 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
3096 prvm_builtin_t vm_sv_builtins[] = {
3097 NULL, // #0 NULL function (not callable) (QUAKE)
3098 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3099 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3100 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3101 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3102 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3103 VM_break, // #6 void() break (QUAKE)
3104 VM_random, // #7 float() random (QUAKE)
3105 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3106 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3107 VM_error, // #10 void(string e) error (QUAKE)
3108 VM_objerror, // #11 void(string e) objerror (QUAKE)
3109 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3110 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3111 VM_spawn, // #14 entity() spawn (QUAKE)
3112 VM_remove, // #15 void(entity e) remove (QUAKE)
3113 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3114 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3115 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3116 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3117 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3118 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3119 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3120 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3121 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3122 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3123 VM_ftos, // #26 string(float f) ftos (QUAKE)
3124 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3125 VM_coredump, // #28 void() coredump (QUAKE)
3126 VM_traceon, // #29 void() traceon (QUAKE)
3127 VM_traceoff, // #30 void() traceoff (QUAKE)
3128 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3129 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3130 NULL, // #33 (QUAKE)
3131 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3132 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3133 VM_rint, // #36 float(float v) rint (QUAKE)
3134 VM_floor, // #37 float(float v) floor (QUAKE)
3135 VM_ceil, // #38 float(float v) ceil (QUAKE)
3136 NULL, // #39 (QUAKE)
3137 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3138 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3139 NULL, // #42 (QUAKE)
3140 VM_fabs, // #43 float(float f) fabs (QUAKE)
3141 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3142 VM_cvar, // #45 float(string s) cvar (QUAKE)
3143 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3144 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3145 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3146 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3147 NULL, // #50 (QUAKE)
3148 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3149 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3150 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3151 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3152 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3153 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3154 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3155 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3156 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3157 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3158 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3159 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3160 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3161 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3162 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3163 NULL, // #66 (QUAKE)
3164 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3165 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3166 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3167 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3168 NULL, // #71 (QUAKE)
3169 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3170 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3171 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3172 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3173 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3174 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3175 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3176 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3177 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3178 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3179 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3180 NULL, // #83 (QUAKE)
3181 NULL, // #84 (QUAKE)
3182 NULL, // #85 (QUAKE)
3183 NULL, // #86 (QUAKE)
3184 NULL, // #87 (QUAKE)
3185 NULL, // #88 (QUAKE)
3186 NULL, // #89 (QUAKE)
3187 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3188 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3189 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3190 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3191 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3192 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3193 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3194 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3195 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3196 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3197 // FrikaC and Telejano range #100-#199
3208 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3209 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3210 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3211 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3212 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3213 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3214 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3215 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3216 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3217 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3298 // FTEQW range #200-#299
3317 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3320 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3321 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3322 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3323 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3324 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3325 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3326 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3327 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3328 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3329 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3331 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3339 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3399 // CSQC range #300-#399
3400 NULL, // #300 void() clearscene (EXT_CSQC)
3401 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3402 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3403 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3404 NULL, // #304 void() renderscene (EXT_CSQC)
3405 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3406 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3407 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3408 NULL, // #308 void() R_EndPolygon
3410 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3411 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3415 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3416 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3417 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3418 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3419 NULL, // #319 void(string name) freepic (EXT_CSQC)
3420 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3421 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3422 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3423 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3424 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3425 NULL, // #325 void(void) drawresetcliparea
3430 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3431 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3432 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3433 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3434 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3435 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3436 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3437 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3438 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3439 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3440 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3441 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3442 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3443 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3444 NULL, // #344 vector() getmousepos (EXT_CSQC)
3445 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3446 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3447 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3448 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3449 NULL, // #349 float() isdemo (EXT_CSQC)
3450 VM_isserver, // #350 float() isserver (EXT_CSQC)
3451 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3452 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3453 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3454 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3460 NULL, // #360 float() readbyte (EXT_CSQC)
3461 NULL, // #361 float() readchar (EXT_CSQC)
3462 NULL, // #362 float() readshort (EXT_CSQC)
3463 NULL, // #363 float() readlong (EXT_CSQC)
3464 NULL, // #364 float() readcoord (EXT_CSQC)
3465 NULL, // #365 float() readangle (EXT_CSQC)
3466 NULL, // #366 string() readstring (EXT_CSQC)
3467 NULL, // #367 float() readfloat (EXT_CSQC)
3500 // LordHavoc's range #400-#499
3501 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3502 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3503 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3504 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3505 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3506 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3507 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3508 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3509 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)
3510 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3511 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3512 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3513 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3514 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3515 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3516 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3517 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3518 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3519 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3520 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3521 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3522 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3523 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3524 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3525 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3526 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3527 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3528 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3529 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3530 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3531 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3532 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3533 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3534 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3535 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3536 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3537 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3538 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3539 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3540 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3541 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3542 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3543 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3544 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3545 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3546 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3547 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3548 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3549 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3550 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3551 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3552 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3553 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3554 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3555 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3556 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3557 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3558 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3560 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3561 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3562 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3563 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3564 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3565 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3566 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3567 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3568 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3569 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3570 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3572 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3573 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3574 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3575 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3576 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3577 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3578 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3579 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3580 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3581 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3582 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3583 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3584 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3585 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3586 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3587 VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3595 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3596 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3597 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3598 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3599 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3600 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3601 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3602 VM_SV_WritePicture, // #501
3604 VM_whichpack, // #503 string(string) whichpack = #503;
3611 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3612 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3613 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3614 VM_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET)
3615 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3616 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3617 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3618 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3619 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3620 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3632 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3725 VM_getextresponse, // #624 string getextresponse(void)
3729 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3731 void VM_SV_Cmd_Init(void)
3736 void VM_SV_Cmd_Reset(void)
3738 World_End(&sv.world);
3739 if(prog->funcoffsets.SV_Shutdown)
3741 func_t s = prog->funcoffsets.SV_Shutdown;
3742 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3743 PRVM_ExecuteProgram(s,"SV_Shutdown() required");