6 //============================================================================
11 char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
22 "DP_CSQC_MULTIFRAME_INTERPOLATION "
38 "DP_ENT_CUSTOMCOLORMAP "
39 "DP_ENT_EXTERIORMODELTOCLIENT "
41 "DP_ENT_LOWPRECISION "
45 "DP_GFX_EXTERNALTEXTURES "
46 "DP_GFX_EXTERNALTEXTURES_PERMAP "
48 "DP_GFX_QUAKE3MODELTAGS "
51 "DP_GFX_MODEL_INTERPOLATION "
53 "DP_HALFLIFE_MAP_CVAR "
59 "DP_MOVETYPEBOUNCEMISSILE "
62 "DP_QC_ASINACOSATANATAN2TAN "
67 "DP_QC_CVAR_DEFSTRING "
68 "DP_QC_CVAR_DESCRIPTION "
74 "DP_QC_EXTRESPONSEPACKET "
76 "DP_QC_FINDCHAIN_TOFIELD "
77 "DP_QC_FINDCHAINFLAGS "
78 "DP_QC_FINDCHAINFLOAT "
84 "DP_QC_GETSURFACEPOINTATTRIBUTE "
86 "DP_QC_GETTAGINFO_BONEPROPERTIES "
88 "DP_QC_GETTIME_CDTRACK "
90 "DP_QC_MULTIPLETEMPSTRINGS "
91 "DP_QC_NUM_FOR_EDICT "
93 "DP_QC_SINCOSSQRTPOW "
95 "DP_QC_STRINGBUFFERS "
96 "DP_QC_STRINGBUFFERS_CVARLIST "
97 "DP_QC_STRINGCOLORFUNCTIONS "
98 "DP_QC_STRING_CASE_FUNCTIONS "
100 "DP_QC_TOKENIZEBYSEPARATOR "
101 "DP_QC_TOKENIZE_CONSOLE "
104 "DP_QC_TRACE_MOVETYPE_HITMODEL "
105 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
106 "DP_QC_UNLIMITEDTEMPSTRINGS "
109 "DP_QC_VECTOANGLES_WITH_ROLL "
110 "DP_QC_VECTORVECTORS "
117 "DP_SND_DIRECTIONLESSATTNNONE "
124 "DP_SV_BOUNCEFACTOR "
125 "DP_SV_CLIENTCOLORS "
128 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
129 "DP_SV_DRAWONLYTOCLIENT "
132 "DP_SV_ENTITYCONTENTSTRANSITION "
133 "DP_SV_MODELFLAGS_AS_EFFECTS "
134 "DP_SV_MOVETYPESTEP_LANDEVENT "
136 "DP_SV_NODRAWTOCLIENT "
137 "DP_SV_ONENTITYNOSPAWNFUNCTION "
138 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
140 "DP_SV_PLAYERPHYSICS "
141 "DP_SV_POINTPARTICLES "
143 "DP_SV_PRECACHEANYTIME "
147 "DP_SV_ROTATINGBMODEL "
151 "DP_SV_SPAWNFUNC_PREFIX "
152 "DP_SV_WRITEPICTURE "
153 "DP_SV_WRITEUNTERMINATEDSTRING "
157 "DP_TE_EXPLOSIONRGB "
159 "DP_TE_PARTICLECUBE "
160 "DP_TE_PARTICLERAIN "
161 "DP_TE_PARTICLESNOW "
163 "DP_TE_QUADEFFECTS1 "
166 "DP_TE_STANDARDEFFECTBUILTINS "
167 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
173 "KRIMZON_SV_PARSECLIENTCOMMAND "
176 "NEXUIZ_PLAYERMODEL "
178 "PRYDON_CLIENTCURSOR "
179 "TENEBRAE_GFX_DLIGHTS "
182 //"EXT_CSQC " // not ready yet
189 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.
191 setorigin (entity, origin)
194 static void VM_SV_setorigin (void)
199 VM_SAFEPARMCOUNT(2, VM_setorigin);
201 e = PRVM_G_EDICT(OFS_PARM0);
202 if (e == prog->edicts)
204 VM_Warning("setorigin: can not modify world entity\n");
207 if (e->priv.server->free)
209 VM_Warning("setorigin: can not modify free entity\n");
212 org = PRVM_G_VECTOR(OFS_PARM1);
213 VectorCopy (org, e->fields.server->origin);
214 SV_LinkEdict (e, false);
217 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
218 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
222 for (i=0 ; i<3 ; i++)
224 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
226 // set derived values
227 VectorCopy (min, e->fields.server->mins);
228 VectorCopy (max, e->fields.server->maxs);
229 VectorSubtract (max, min, e->fields.server->size);
231 SV_LinkEdict (e, false);
238 the size box is rotated by the current angle
239 LordHavoc: no it isn't...
241 setsize (entity, minvector, maxvector)
244 static void VM_SV_setsize (void)
249 VM_SAFEPARMCOUNT(3, VM_setsize);
251 e = PRVM_G_EDICT(OFS_PARM0);
252 if (e == prog->edicts)
254 VM_Warning("setsize: can not modify world entity\n");
257 if (e->priv.server->free)
259 VM_Warning("setsize: can not modify free entity\n");
262 min = PRVM_G_VECTOR(OFS_PARM1);
263 max = PRVM_G_VECTOR(OFS_PARM2);
264 SetMinMaxSize (e, min, max, false);
272 setmodel(entity, model)
275 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
276 static void VM_SV_setmodel (void)
282 VM_SAFEPARMCOUNT(2, VM_setmodel);
284 e = PRVM_G_EDICT(OFS_PARM0);
285 if (e == prog->edicts)
287 VM_Warning("setmodel: can not modify world entity\n");
290 if (e->priv.server->free)
292 VM_Warning("setmodel: can not modify free entity\n");
295 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
296 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
297 e->fields.server->modelindex = i;
303 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
304 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
306 SetMinMaxSize (e, quakemins, quakemaxs, true);
309 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
316 single print to a specific client
318 sprint(clientent, value)
321 static void VM_SV_sprint (void)
325 char string[VM_STRINGTEMP_LENGTH];
327 VM_VarString(1, string, sizeof(string));
329 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
331 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
332 // LordHavoc: div0 requested that sprintto world operate like print
339 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
341 VM_Warning("tried to centerprint to a non-client\n");
345 client = svs.clients + entnum-1;
346 if (!client->netconnection)
349 MSG_WriteChar(&client->netconnection->message,svc_print);
350 MSG_WriteString(&client->netconnection->message, string);
358 single print to a specific client
360 centerprint(clientent, value)
363 static void VM_SV_centerprint (void)
367 char string[VM_STRINGTEMP_LENGTH];
369 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
371 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
373 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
375 VM_Warning("tried to centerprint to a non-client\n");
379 client = svs.clients + entnum-1;
380 if (!client->netconnection)
383 VM_VarString(1, string, sizeof(string));
384 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
385 MSG_WriteString(&client->netconnection->message, string);
392 particle(origin, color, count)
395 static void VM_SV_particle (void)
401 VM_SAFEPARMCOUNT(4, VM_SV_particle);
403 org = PRVM_G_VECTOR(OFS_PARM0);
404 dir = PRVM_G_VECTOR(OFS_PARM1);
405 color = PRVM_G_FLOAT(OFS_PARM2);
406 count = PRVM_G_FLOAT(OFS_PARM3);
407 SV_StartParticle (org, dir, (int)color, (int)count);
417 static void VM_SV_ambientsound (void)
421 float vol, attenuation;
424 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
426 pos = PRVM_G_VECTOR (OFS_PARM0);
427 samp = PRVM_G_STRING(OFS_PARM1);
428 vol = PRVM_G_FLOAT(OFS_PARM2);
429 attenuation = PRVM_G_FLOAT(OFS_PARM3);
431 // check to see if samp was properly precached
432 soundnum = SV_SoundIndex(samp, 1);
440 // add an svc_spawnambient command to the level signon packet
443 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
445 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
447 MSG_WriteVector(&sv.signon, pos, sv.protocol);
449 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
450 MSG_WriteShort (&sv.signon, soundnum);
452 MSG_WriteByte (&sv.signon, soundnum);
454 MSG_WriteByte (&sv.signon, (int)(vol*255));
455 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
463 Each entity can have eight independant sound sources, like voice,
466 Channel 0 is an auto-allocate channel, the others override anything
467 already running on that entity/channel pair.
469 An attenuation of 0 will play full volume everywhere in the level.
470 Larger attenuations will drop off.
474 static void VM_SV_sound (void)
478 prvm_edict_t *entity;
482 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
484 entity = PRVM_G_EDICT(OFS_PARM0);
485 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
486 sample = PRVM_G_STRING(OFS_PARM2);
487 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
488 attenuation = PRVM_G_FLOAT(OFS_PARM4);
491 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
495 if (volume < 0 || volume > 255)
497 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
501 if (attenuation < 0 || attenuation > 4)
503 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
507 if (channel < 0 || channel > 7)
509 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
513 SV_StartSound (entity, channel, sample, volume, attenuation);
520 Follows the same logic as VM_SV_sound, except instead of
521 an entity, an origin for the sound is provided, and channel
522 is omitted (since no entity is being tracked).
526 static void VM_SV_pointsound(void)
533 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
535 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
536 sample = PRVM_G_STRING(OFS_PARM1);
537 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
538 attenuation = PRVM_G_FLOAT(OFS_PARM3);
540 if (volume < 0 || volume > 255)
542 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
546 if (attenuation < 0 || attenuation > 4)
548 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
552 SV_StartPointSound (org, sample, volume, attenuation);
559 Used for use tracing and shot targeting
560 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
561 if the tryents flag is set.
563 traceline (vector1, vector2, movetype, ignore)
566 static void VM_SV_traceline (void)
573 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
575 prog->xfunction->builtinsprofile += 30;
577 v1 = PRVM_G_VECTOR(OFS_PARM0);
578 v2 = PRVM_G_VECTOR(OFS_PARM1);
579 move = (int)PRVM_G_FLOAT(OFS_PARM2);
580 ent = PRVM_G_EDICT(OFS_PARM3);
582 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]))
583 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));
585 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
587 VM_SetTraceGlobals(&trace);
595 Used for use tracing and shot targeting
596 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
597 if the tryents flag is set.
599 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
602 // LordHavoc: added this for my own use, VERY useful, similar to traceline
603 static void VM_SV_tracebox (void)
605 float *v1, *v2, *m1, *m2;
610 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
612 prog->xfunction->builtinsprofile += 30;
614 v1 = PRVM_G_VECTOR(OFS_PARM0);
615 m1 = PRVM_G_VECTOR(OFS_PARM1);
616 m2 = PRVM_G_VECTOR(OFS_PARM2);
617 v2 = PRVM_G_VECTOR(OFS_PARM3);
618 move = (int)PRVM_G_FLOAT(OFS_PARM4);
619 ent = PRVM_G_EDICT(OFS_PARM5);
621 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]))
622 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));
624 trace = SV_Move (v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
626 VM_SetTraceGlobals(&trace);
629 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
634 vec3_t original_origin;
635 vec3_t original_velocity;
636 vec3_t original_angles;
637 vec3_t original_avelocity;
641 VectorCopy(tossent->fields.server->origin , original_origin );
642 VectorCopy(tossent->fields.server->velocity , original_velocity );
643 VectorCopy(tossent->fields.server->angles , original_angles );
644 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
646 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
647 if (val != NULL && val->_float != 0)
648 gravity = val->_float;
651 gravity *= sv_gravity.value * 0.025;
653 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
655 SV_CheckVelocity (tossent);
656 tossent->fields.server->velocity[2] -= gravity;
657 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
658 VectorScale (tossent->fields.server->velocity, 0.05, move);
659 VectorAdd (tossent->fields.server->origin, move, end);
660 trace = SV_Move (tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
661 VectorCopy (trace.endpos, tossent->fields.server->origin);
662 tossent->fields.server->velocity[2] -= gravity;
664 if (trace.fraction < 1)
668 VectorCopy(original_origin , tossent->fields.server->origin );
669 VectorCopy(original_velocity , tossent->fields.server->velocity );
670 VectorCopy(original_angles , tossent->fields.server->angles );
671 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
676 static void VM_SV_tracetoss (void)
680 prvm_edict_t *ignore;
682 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
684 prog->xfunction->builtinsprofile += 600;
686 ent = PRVM_G_EDICT(OFS_PARM0);
687 if (ent == prog->edicts)
689 VM_Warning("tracetoss: can not use world entity\n");
692 ignore = PRVM_G_EDICT(OFS_PARM1);
694 trace = SV_Trace_Toss (ent, ignore);
696 VM_SetTraceGlobals(&trace);
699 //============================================================================
701 static int checkpvsbytes;
702 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
704 static int VM_SV_newcheckclient (int check)
710 // cycle to the next one
712 check = bound(1, check, svs.maxclients);
713 if (check == svs.maxclients)
721 prog->xfunction->builtinsprofile++;
723 if (i == svs.maxclients+1)
725 // look up the client's edict
726 ent = PRVM_EDICT_NUM(i);
727 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
728 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
730 // found a valid client (possibly the same one again)
734 // get the PVS for the entity
735 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
737 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
738 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
747 Returns a client (or object that has a client enemy) that would be a
750 If there is more than one valid option, they are cycled each frame
752 If (self.origin + self.viewofs) is not in the PVS of the current target,
753 it is not returned at all.
758 int c_invis, c_notvis;
759 static void VM_SV_checkclient (void)
761 prvm_edict_t *ent, *self;
764 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
766 // find a new check if on a new frame
767 if (sv.time - sv.lastchecktime >= 0.1)
769 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
770 sv.lastchecktime = sv.time;
773 // return check if it might be visible
774 ent = PRVM_EDICT_NUM(sv.lastcheck);
775 if (ent->priv.server->free || ent->fields.server->health <= 0)
777 VM_RETURN_EDICT(prog->edicts);
781 // if current entity can't possibly see the check entity, return 0
782 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
783 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
784 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
787 VM_RETURN_EDICT(prog->edicts);
791 // might be able to see it
793 VM_RETURN_EDICT(ent);
796 //============================================================================
802 Checks if an entity is in a point's PVS.
803 Should be fast but can be inexact.
805 float checkpvs(vector viewpos, entity viewee) = #240;
808 static void VM_SV_checkpvs (void)
811 prvm_edict_t *viewee;
815 static int fatpvsbytes;
816 static unsigned char fatpvs[MAX_MAP_LEAFS/8];
819 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
820 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
821 viewee = PRVM_G_EDICT(OFS_PARM1);
823 if(viewee->priv.server->free)
825 VM_Warning("checkpvs: can not check free entity\n");
826 PRVM_G_FLOAT(OFS_RETURN) = 4;
831 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
833 // no PVS support on this worldmodel... darn
834 PRVM_G_FLOAT(OFS_RETURN) = 3;
837 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
840 // viewpos isn't in any PVS... darn
841 PRVM_G_FLOAT(OFS_RETURN) = 2;
844 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
846 // using fat PVS like FTEQW does (slow)
847 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
849 // no PVS support on this worldmodel... darn
850 PRVM_G_FLOAT(OFS_RETURN) = 3;
853 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
856 // viewpos isn't in any PVS... darn
857 PRVM_G_FLOAT(OFS_RETURN) = 2;
860 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
869 Sends text over to the client's execution buffer
871 stuffcmd (clientent, value, ...)
874 static void VM_SV_stuffcmd (void)
878 char string[VM_STRINGTEMP_LENGTH];
880 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
882 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
883 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
885 VM_Warning("Can't stuffcmd to a non-client\n");
889 VM_VarString(1, string, sizeof(string));
892 host_client = svs.clients + entnum-1;
893 Host_ClientCommands ("%s", string);
901 Returns a chain of entities that have origins within a spherical area
903 findradius (origin, radius)
906 static void VM_SV_findradius (void)
908 prvm_edict_t *ent, *chain;
909 vec_t radius, radius2;
910 vec3_t org, eorg, mins, maxs;
913 prvm_edict_t *touchedicts[MAX_EDICTS];
916 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
919 chainfield = PRVM_G_INT(OFS_PARM2);
921 chainfield = prog->fieldoffsets.chain;
923 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
925 chain = (prvm_edict_t *)prog->edicts;
927 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
928 radius = PRVM_G_FLOAT(OFS_PARM1);
929 radius2 = radius * radius;
931 mins[0] = org[0] - (radius + 1);
932 mins[1] = org[1] - (radius + 1);
933 mins[2] = org[2] - (radius + 1);
934 maxs[0] = org[0] + (radius + 1);
935 maxs[1] = org[1] + (radius + 1);
936 maxs[2] = org[2] + (radius + 1);
937 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
938 if (numtouchedicts > MAX_EDICTS)
940 // this never happens
941 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
942 numtouchedicts = MAX_EDICTS;
944 for (i = 0;i < numtouchedicts;i++)
946 ent = touchedicts[i];
947 prog->xfunction->builtinsprofile++;
948 // Quake did not return non-solid entities but darkplaces does
949 // (note: this is the reason you can't blow up fallen zombies)
950 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
952 // LordHavoc: compare against bounding box rather than center so it
953 // doesn't miss large objects, and use DotProduct instead of Length
954 // for a major speedup
955 VectorSubtract(org, ent->fields.server->origin, eorg);
956 if (sv_gameplayfix_findradiusdistancetobox.integer)
958 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
959 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
960 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
963 VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
964 if (DotProduct(eorg, eorg) < radius2)
966 PRVM_EDICTFIELDVALUE(ent,chainfield)->edict = PRVM_EDICT_TO_PROG(chain);
971 VM_RETURN_EDICT(chain);
974 static void VM_SV_precache_sound (void)
976 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
977 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
980 static void VM_SV_precache_model (void)
982 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
983 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
984 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
991 float(float yaw, float dist[, settrace]) walkmove
994 static void VM_SV_walkmove (void)
1003 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1005 // assume failure if it returns early
1006 PRVM_G_FLOAT(OFS_RETURN) = 0;
1008 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1009 if (ent == prog->edicts)
1011 VM_Warning("walkmove: can not modify world entity\n");
1014 if (ent->priv.server->free)
1016 VM_Warning("walkmove: can not modify free entity\n");
1019 yaw = PRVM_G_FLOAT(OFS_PARM0);
1020 dist = PRVM_G_FLOAT(OFS_PARM1);
1021 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1023 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1026 yaw = yaw*M_PI*2 / 360;
1028 move[0] = cos(yaw)*dist;
1029 move[1] = sin(yaw)*dist;
1032 // save program state, because SV_movestep may call other progs
1033 oldf = prog->xfunction;
1034 oldself = prog->globals.server->self;
1036 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1039 // restore program state
1040 prog->xfunction = oldf;
1041 prog->globals.server->self = oldself;
1051 static void VM_SV_droptofloor (void)
1057 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1059 // assume failure if it returns early
1060 PRVM_G_FLOAT(OFS_RETURN) = 0;
1062 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1063 if (ent == prog->edicts)
1065 VM_Warning("droptofloor: can not modify world entity\n");
1068 if (ent->priv.server->free)
1070 VM_Warning("droptofloor: can not modify free entity\n");
1074 VectorCopy (ent->fields.server->origin, end);
1077 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1078 SV_UnstickEntity(ent);
1080 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1081 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1084 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]);
1085 VectorAdd(ent->fields.server->origin, offset, org);
1086 trace = SV_Move (org, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1087 VectorSubtract(trace.endpos, offset, trace.endpos);
1088 if (trace.startsolid)
1090 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]);
1091 SV_UnstickEntity(ent);
1092 SV_LinkEdict (ent, false);
1093 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1094 ent->fields.server->groundentity = 0;
1095 PRVM_G_FLOAT(OFS_RETURN) = 1;
1097 else if (trace.fraction < 1)
1099 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]);
1100 VectorCopy (trace.endpos, ent->fields.server->origin);
1101 SV_UnstickEntity(ent);
1102 SV_LinkEdict (ent, false);
1103 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1104 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1105 PRVM_G_FLOAT(OFS_RETURN) = 1;
1106 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1107 ent->priv.server->suspendedinairflag = true;
1112 if (trace.fraction != 1)
1114 if (trace.fraction < 1)
1115 VectorCopy (trace.endpos, ent->fields.server->origin);
1116 SV_LinkEdict (ent, false);
1117 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1118 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1119 PRVM_G_FLOAT(OFS_RETURN) = 1;
1120 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1121 ent->priv.server->suspendedinairflag = true;
1130 void(float style, string value) lightstyle
1133 static void VM_SV_lightstyle (void)
1140 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1142 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1143 val = PRVM_G_STRING(OFS_PARM1);
1145 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1146 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1149 // change the string in sv
1150 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1152 // send message to all clients on this server
1153 if (sv.state != ss_active)
1156 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1158 if (client->active && client->netconnection)
1160 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1161 MSG_WriteChar (&client->netconnection->message,style);
1162 MSG_WriteString (&client->netconnection->message, val);
1172 static void VM_SV_checkbottom (void)
1174 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1175 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1183 static void VM_SV_pointcontents (void)
1185 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1186 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1193 Pick a vector for the player to shoot along
1194 vector aim(entity, missilespeed)
1197 static void VM_SV_aim (void)
1199 prvm_edict_t *ent, *check, *bestent;
1200 vec3_t start, dir, end, bestdir;
1203 float dist, bestdist;
1206 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1208 // assume failure if it returns early
1209 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1210 // if sv_aim is so high it can't possibly accept anything, skip out early
1211 if (sv_aim.value >= 1)
1214 ent = PRVM_G_EDICT(OFS_PARM0);
1215 if (ent == prog->edicts)
1217 VM_Warning("aim: can not use world entity\n");
1220 if (ent->priv.server->free)
1222 VM_Warning("aim: can not use free entity\n");
1225 speed = PRVM_G_FLOAT(OFS_PARM1);
1227 VectorCopy (ent->fields.server->origin, start);
1230 // try sending a trace straight
1231 VectorCopy (prog->globals.server->v_forward, dir);
1232 VectorMA (start, 2048, dir, end);
1233 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1234 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1235 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1237 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1242 // try all possible entities
1243 VectorCopy (dir, bestdir);
1244 bestdist = sv_aim.value;
1247 check = PRVM_NEXT_EDICT(prog->edicts);
1248 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1250 prog->xfunction->builtinsprofile++;
1251 if (check->fields.server->takedamage != DAMAGE_AIM)
1255 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1256 continue; // don't aim at teammate
1257 for (j=0 ; j<3 ; j++)
1258 end[j] = check->fields.server->origin[j]
1259 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1260 VectorSubtract (end, start, dir);
1261 VectorNormalize (dir);
1262 dist = DotProduct (dir, prog->globals.server->v_forward);
1263 if (dist < bestdist)
1264 continue; // to far to turn
1265 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1266 if (tr.ent == check)
1267 { // can shoot at this one
1275 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1276 dist = DotProduct (dir, prog->globals.server->v_forward);
1277 VectorScale (prog->globals.server->v_forward, dist, end);
1279 VectorNormalize (end);
1280 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1284 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1289 ===============================================================================
1293 ===============================================================================
1296 #define MSG_BROADCAST 0 // unreliable to all
1297 #define MSG_ONE 1 // reliable to one (msg_entity)
1298 #define MSG_ALL 2 // reliable to all
1299 #define MSG_INIT 3 // write to the init string
1300 #define MSG_ENTITY 5
1302 sizebuf_t *WriteDest (void)
1308 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1312 return &sv.datagram;
1315 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1316 entnum = PRVM_NUM_FOR_EDICT(ent);
1317 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1319 VM_Warning ("WriteDest: tried to write to non-client\n");
1320 return &sv.reliable_datagram;
1323 return &svs.clients[entnum-1].netconnection->message;
1326 VM_Warning ("WriteDest: bad destination\n");
1328 return &sv.reliable_datagram;
1334 return sv.writeentitiestoclient_msg;
1340 static void VM_SV_WriteByte (void)
1342 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1343 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1346 static void VM_SV_WriteChar (void)
1348 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1349 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1352 static void VM_SV_WriteShort (void)
1354 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1355 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1358 static void VM_SV_WriteLong (void)
1360 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1361 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1364 static void VM_SV_WriteAngle (void)
1366 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1367 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1370 static void VM_SV_WriteCoord (void)
1372 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1373 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1376 static void VM_SV_WriteString (void)
1378 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1379 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1382 static void VM_SV_WriteUnterminatedString (void)
1384 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1385 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1388 static void VM_SV_WriteEntity (void)
1390 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1391 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1394 static void VM_SV_WriteByteINT (void)
1396 VM_SAFEPARMCOUNT(2, VM_SV_WriteByteINT);
1397 MSG_WriteByte (WriteDest(), PRVM_G_INT(OFS_PARM1));
1400 static void VM_SV_WriteCharINT (void)
1402 VM_SAFEPARMCOUNT(2, VM_SV_WriteCharINT);
1403 MSG_WriteChar (WriteDest(), PRVM_G_INT(OFS_PARM1));
1406 static void VM_SV_WriteShortINT (void)
1408 VM_SAFEPARMCOUNT(2, VM_SV_WriteShortINT);
1409 MSG_WriteShort (WriteDest(), PRVM_G_INT(OFS_PARM1));
1412 static void VM_SV_WriteLongINT (void)
1414 VM_SAFEPARMCOUNT(2, VM_SV_WriteLongINT);
1415 MSG_WriteLong (WriteDest(), PRVM_G_INT(OFS_PARM1));
1419 // writes a picture as at most size bytes of data
1421 // IMGNAME \0 SIZE(short) IMGDATA
1422 // if failed to read/compress:
1424 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1425 static void VM_SV_WritePicture (void)
1427 const char *imgname;
1431 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1433 imgname = PRVM_G_STRING(OFS_PARM1);
1434 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1438 MSG_WriteString(WriteDest(), imgname);
1439 if(Image_Compress(imgname, size, &buf, &size))
1442 MSG_WriteShort(WriteDest(), size);
1443 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1448 MSG_WriteShort(WriteDest(), 0);
1452 //////////////////////////////////////////////////////////
1454 static void VM_SV_makestatic (void)
1459 // allow 0 parameters due to an id1 qc bug in which this function is used
1460 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1461 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1463 if (prog->argc >= 1)
1464 ent = PRVM_G_EDICT(OFS_PARM0);
1466 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1467 if (ent == prog->edicts)
1469 VM_Warning("makestatic: can not modify world entity\n");
1472 if (ent->priv.server->free)
1474 VM_Warning("makestatic: can not modify free entity\n");
1479 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1484 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1485 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1486 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1488 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1490 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1491 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1492 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1496 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1497 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1498 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1501 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1502 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1503 for (i=0 ; i<3 ; i++)
1505 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1506 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1509 // throw the entity away now
1513 //=============================================================================
1520 static void VM_SV_setspawnparms (void)
1526 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1528 ent = PRVM_G_EDICT(OFS_PARM0);
1529 i = PRVM_NUM_FOR_EDICT(ent);
1530 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1532 Con_Print("tried to setspawnparms on a non-client\n");
1536 // copy spawn parms out of the client_t
1537 client = svs.clients + i-1;
1538 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1539 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1546 Returns a color vector indicating the lighting at the requested point.
1548 (Internal Operation note: actually measures the light beneath the point, just like
1549 the model lighting on the client)
1554 static void VM_SV_getlight (void)
1556 vec3_t ambientcolor, diffusecolor, diffusenormal;
1558 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1559 p = PRVM_G_VECTOR(OFS_PARM0);
1560 VectorClear(ambientcolor);
1561 VectorClear(diffusecolor);
1562 VectorClear(diffusenormal);
1563 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1564 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1565 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1570 unsigned char type; // 1/2/8 or other value if isn't used
1574 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1575 static int vm_customstats_last;
1577 void VM_CustomStats_Clear (void)
1581 Z_Free(vm_customstats);
1582 vm_customstats = NULL;
1583 vm_customstats_last = -1;
1587 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1595 for(i=0; i<vm_customstats_last+1 ;i++)
1597 if(!vm_customstats[i].type)
1599 switch(vm_customstats[i].type)
1601 //string as 16 bytes
1604 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1605 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1606 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1607 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1608 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1610 //float field sent as-is
1612 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1614 //integer value of float field
1616 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1624 // void(float index, float type, .void field) SV_AddStat = #232;
1625 // Set up an auto-sent player stat.
1626 // Client's get thier own fields sent to them. Index may not be less than 32.
1627 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1628 // 1: string (4 stats carrying a total of 16 charactures)
1629 // 2: float (one stat, float converted to an integer for transportation)
1630 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1631 static void VM_SV_AddStat (void)
1636 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1640 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1643 VM_Warning("PF_SV_AddStat: not enough memory\n");
1647 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1648 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1649 off = PRVM_G_INT (OFS_PARM2);
1654 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1657 if(i >= (MAX_CL_STATS-32))
1659 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1662 if(i > (MAX_CL_STATS-32-4) && type == 1)
1664 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1667 vm_customstats[i].type = type;
1668 vm_customstats[i].fieldoffset = off;
1669 if(vm_customstats_last < i)
1670 vm_customstats_last = i;
1677 copies data from one entity to another
1679 copyentity(src, dst)
1682 static void VM_SV_copyentity (void)
1684 prvm_edict_t *in, *out;
1685 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1686 in = PRVM_G_EDICT(OFS_PARM0);
1687 if (in == prog->edicts)
1689 VM_Warning("copyentity: can not read world entity\n");
1692 if (in->priv.server->free)
1694 VM_Warning("copyentity: can not read free entity\n");
1697 out = PRVM_G_EDICT(OFS_PARM1);
1698 if (out == prog->edicts)
1700 VM_Warning("copyentity: can not modify world entity\n");
1703 if (out->priv.server->free)
1705 VM_Warning("copyentity: can not modify free entity\n");
1708 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1709 SV_LinkEdict(out, false);
1717 sets the color of a client and broadcasts the update to all connected clients
1719 setcolor(clientent, value)
1722 static void VM_SV_setcolor (void)
1728 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1729 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1730 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1732 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1734 Con_Print("tried to setcolor a non-client\n");
1738 client = svs.clients + entnum-1;
1741 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1743 client->edict->fields.server->team = (i & 15) + 1;
1746 if (client->old_colors != client->colors)
1748 client->old_colors = client->colors;
1749 // send notification to all clients
1750 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1751 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1752 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1760 effect(origin, modelname, startframe, framecount, framerate)
1763 static void VM_SV_effect (void)
1767 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1768 s = PRVM_G_STRING(OFS_PARM1);
1771 VM_Warning("effect: no model specified\n");
1775 i = SV_ModelIndex(s, 1);
1778 VM_Warning("effect: model not precached\n");
1782 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1784 VM_Warning("effect: framecount < 1\n");
1788 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1790 VM_Warning("effect: framerate < 1\n");
1794 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));
1797 static void VM_SV_te_blood (void)
1799 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1800 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1802 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1803 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1805 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1809 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1810 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1811 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1813 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1814 SV_FlushBroadcastMessages();
1817 static void VM_SV_te_bloodshower (void)
1819 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1820 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1822 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1823 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1825 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1826 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1827 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1830 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1831 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1833 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1835 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1836 SV_FlushBroadcastMessages();
1839 static void VM_SV_te_explosionrgb (void)
1841 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1842 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1843 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1845 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1847 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1849 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1850 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1851 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1852 SV_FlushBroadcastMessages();
1855 static void VM_SV_te_particlecube (void)
1857 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1858 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1860 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1861 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1863 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1864 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1865 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1868 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1869 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1873 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1875 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1877 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1878 // gravity true/false
1879 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1881 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1882 SV_FlushBroadcastMessages();
1885 static void VM_SV_te_particlerain (void)
1887 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1888 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1890 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1891 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1893 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1894 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1895 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1905 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1907 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1908 SV_FlushBroadcastMessages();
1911 static void VM_SV_te_particlesnow (void)
1913 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1914 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1916 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1917 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1919 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1920 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1921 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1923 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1924 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1925 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1931 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1933 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1934 SV_FlushBroadcastMessages();
1937 static void VM_SV_te_spark (void)
1939 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1940 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1942 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1943 MSG_WriteByte(&sv.datagram, TE_SPARK);
1945 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1949 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1950 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1951 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1953 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1954 SV_FlushBroadcastMessages();
1957 static void VM_SV_te_gunshotquad (void)
1959 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1960 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1961 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1964 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1965 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1966 SV_FlushBroadcastMessages();
1969 static void VM_SV_te_spikequad (void)
1971 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1972 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1973 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1975 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1976 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1977 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1978 SV_FlushBroadcastMessages();
1981 static void VM_SV_te_superspikequad (void)
1983 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1984 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1985 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1989 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1990 SV_FlushBroadcastMessages();
1993 static void VM_SV_te_explosionquad (void)
1995 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
1996 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1997 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1999 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2000 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2001 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2002 SV_FlushBroadcastMessages();
2005 static void VM_SV_te_smallflash (void)
2007 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2008 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2009 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2011 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2012 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2014 SV_FlushBroadcastMessages();
2017 static void VM_SV_te_customflash (void)
2019 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2020 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2022 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2023 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2025 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2026 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2029 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2031 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2033 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2034 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2035 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2036 SV_FlushBroadcastMessages();
2039 static void VM_SV_te_gunshot (void)
2041 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2042 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2043 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2045 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2046 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2047 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2048 SV_FlushBroadcastMessages();
2051 static void VM_SV_te_spike (void)
2053 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2054 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2055 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2058 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2059 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2060 SV_FlushBroadcastMessages();
2063 static void VM_SV_te_superspike (void)
2065 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2066 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2067 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2069 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2070 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2071 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2072 SV_FlushBroadcastMessages();
2075 static void VM_SV_te_explosion (void)
2077 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2078 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2079 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2081 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2082 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2083 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2084 SV_FlushBroadcastMessages();
2087 static void VM_SV_te_tarexplosion (void)
2089 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2090 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2091 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2093 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2094 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2095 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2096 SV_FlushBroadcastMessages();
2099 static void VM_SV_te_wizspike (void)
2101 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2102 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2103 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2105 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2106 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2107 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2108 SV_FlushBroadcastMessages();
2111 static void VM_SV_te_knightspike (void)
2113 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2114 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2115 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2117 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2118 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2119 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2120 SV_FlushBroadcastMessages();
2123 static void VM_SV_te_lavasplash (void)
2125 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2126 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2127 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2129 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2130 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2131 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2132 SV_FlushBroadcastMessages();
2135 static void VM_SV_te_teleport (void)
2137 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2138 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2139 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2141 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2142 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2143 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2144 SV_FlushBroadcastMessages();
2147 static void VM_SV_te_explosion2 (void)
2149 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2150 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2151 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2153 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2154 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2155 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2157 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2158 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2159 SV_FlushBroadcastMessages();
2162 static void VM_SV_te_lightning1 (void)
2164 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2165 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2166 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2168 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2170 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2171 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2172 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2174 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2175 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2176 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2177 SV_FlushBroadcastMessages();
2180 static void VM_SV_te_lightning2 (void)
2182 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2183 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2184 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2186 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2188 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2189 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2190 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2192 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2193 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2194 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2195 SV_FlushBroadcastMessages();
2198 static void VM_SV_te_lightning3 (void)
2200 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2201 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2202 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2204 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2206 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2207 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2208 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2210 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2211 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2212 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2213 SV_FlushBroadcastMessages();
2216 static void VM_SV_te_beam (void)
2218 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2219 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2220 MSG_WriteByte(&sv.datagram, TE_BEAM);
2222 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2224 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2225 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2226 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2230 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2231 SV_FlushBroadcastMessages();
2234 static void VM_SV_te_plasmaburn (void)
2236 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2237 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2238 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2239 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2240 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2241 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2242 SV_FlushBroadcastMessages();
2245 static void VM_SV_te_flamejet (void)
2247 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2248 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2249 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2251 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2252 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2253 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2255 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2256 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2257 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2259 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2260 SV_FlushBroadcastMessages();
2263 void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2266 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2268 bestdist = 1000000000;
2270 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2272 // clip original point to each triangle of the surface and find the
2273 // triangle that is closest
2274 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2275 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2276 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2277 TriangleNormal(v[0], v[1], v[2], facenormal);
2278 VectorNormalize(facenormal);
2279 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2280 VectorMA(p, offsetdist, facenormal, temp);
2281 for (j = 0, k = 2;j < 3;k = j, j++)
2283 VectorSubtract(v[k], v[j], edgenormal);
2284 CrossProduct(edgenormal, facenormal, sidenormal);
2285 VectorNormalize(sidenormal);
2286 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2288 VectorMA(temp, offsetdist, sidenormal, temp);
2290 dist = VectorDistance2(temp, p);
2291 if (bestdist > dist)
2294 VectorCopy(temp, out);
2299 static dp_model_t *getmodel(prvm_edict_t *ed)
2302 if (!ed || ed->priv.server->free)
2304 modelindex = (int)ed->fields.server->modelindex;
2305 if (modelindex < 1 || modelindex >= MAX_MODELS)
2307 return sv.models[modelindex];
2310 static msurface_t *getsurface(dp_model_t *model, int surfacenum)
2312 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2314 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2318 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2319 static void VM_SV_getsurfacenumpoints(void)
2322 msurface_t *surface;
2323 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints);
2324 // return 0 if no such surface
2325 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2327 PRVM_G_FLOAT(OFS_RETURN) = 0;
2331 // note: this (incorrectly) assumes it is a simple polygon
2332 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2334 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2335 static void VM_SV_getsurfacepoint(void)
2339 msurface_t *surface;
2341 VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint);
2342 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2343 ed = PRVM_G_EDICT(OFS_PARM0);
2344 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2346 // note: this (incorrectly) assumes it is a simple polygon
2347 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2348 if (pointnum < 0 || pointnum >= surface->num_vertices)
2350 // FIXME: implement rotation/scaling
2351 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2353 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
2354 // float SPA_POSITION = 0;
2355 // float SPA_S_AXIS = 1;
2356 // float SPA_T_AXIS = 2;
2357 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2358 // float SPA_TEXCOORDS0 = 4;
2359 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2360 // float SPA_LIGHTMAP0_COLOR = 6;
2361 static void VM_SV_getsurfacepointattribute(void)
2365 msurface_t *surface;
2369 VM_SAFEPARMCOUNT(4, VM_SV_getsurfacepoint);
2370 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2371 ed = PRVM_G_EDICT(OFS_PARM0);
2372 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2374 // note: this (incorrectly) assumes it is a simple polygon
2375 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2376 if (pointnum < 0 || pointnum >= surface->num_vertices)
2378 // FIXME: implement rotation/scaling
2379 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
2381 switch( attributetype ) {
2382 // float SPA_POSITION = 0;
2384 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2386 // float SPA_S_AXIS = 1;
2388 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2390 // float SPA_T_AXIS = 2;
2392 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2394 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2396 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2398 // float SPA_TEXCOORDS0 = 4;
2400 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2401 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
2402 ret[0] = texcoord[0];
2403 ret[1] = texcoord[1];
2407 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2409 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2410 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
2411 ret[0] = texcoord[0];
2412 ret[1] = texcoord[1];
2416 // float SPA_LIGHTMAP0_COLOR = 6;
2418 // ignore alpha for now..
2419 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2422 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2426 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2427 static void VM_SV_getsurfacenormal(void)
2430 msurface_t *surface;
2432 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal);
2433 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2434 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2436 // FIXME: implement rotation/scaling
2437 // note: this (incorrectly) assumes it is a simple polygon
2438 // note: this only returns the first triangle, so it doesn't work very
2439 // well for curved surfaces or arbitrary meshes
2440 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);
2441 VectorNormalize(normal);
2442 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2444 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2445 static void VM_SV_getsurfacetexture(void)
2448 msurface_t *surface;
2449 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture);
2450 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2451 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2453 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2455 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2456 static void VM_SV_getsurfacenearpoint(void)
2458 int surfacenum, best;
2460 vec_t dist, bestdist;
2463 msurface_t *surface;
2465 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint);
2466 PRVM_G_FLOAT(OFS_RETURN) = -1;
2467 ed = PRVM_G_EDICT(OFS_PARM0);
2468 point = PRVM_G_VECTOR(OFS_PARM1);
2470 if (!ed || ed->priv.server->free)
2472 model = getmodel(ed);
2473 if (!model || !model->num_surfaces)
2476 // FIXME: implement rotation/scaling
2477 VectorSubtract(point, ed->fields.server->origin, p);
2479 bestdist = 1000000000;
2480 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2482 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2483 // first see if the nearest point on the surface's box is closer than the previous match
2484 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2485 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2486 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2487 dist = VectorLength2(clipped);
2488 if (dist < bestdist)
2490 // it is, check the nearest point on the actual geometry
2491 clippointtosurface(model, surface, p, clipped);
2492 VectorSubtract(clipped, p, clipped);
2493 dist += VectorLength2(clipped);
2494 if (dist < bestdist)
2496 // that's closer too, store it as the best match
2502 PRVM_G_FLOAT(OFS_RETURN) = best;
2504 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2505 static void VM_SV_getsurfaceclippedpoint(void)
2509 msurface_t *surface;
2511 VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint);
2512 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2513 ed = PRVM_G_EDICT(OFS_PARM0);
2514 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2516 // FIXME: implement rotation/scaling
2517 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2518 clippointtosurface(model, surface, p, out);
2519 // FIXME: implement rotation/scaling
2520 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2523 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2524 //this function originally written by KrimZon, made shorter by LordHavoc
2525 static void VM_SV_clientcommand (void)
2527 client_t *temp_client;
2529 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2531 //find client for this entity
2532 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2533 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2535 Con_Print("PF_clientcommand: entity is not a client\n");
2539 temp_client = host_client;
2540 host_client = svs.clients + i;
2541 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2542 host_client = temp_client;
2545 //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)
2546 static void VM_SV_setattachment (void)
2548 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2549 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2550 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2554 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2556 if (e == prog->edicts)
2558 VM_Warning("setattachment: can not modify world entity\n");
2561 if (e->priv.server->free)
2563 VM_Warning("setattachment: can not modify free entity\n");
2567 if (tagentity == NULL)
2568 tagentity = prog->edicts;
2570 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2572 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2574 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2577 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2579 modelindex = (int)tagentity->fields.server->modelindex;
2580 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2582 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2584 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);
2587 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));
2591 /////////////////////////////////////////
2592 // DP_MD3_TAGINFO extension coded by VorteX
2594 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2599 i = (int)e->fields.server->modelindex;
2600 if (i < 1 || i >= MAX_MODELS)
2602 model = sv.models[i];
2604 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2607 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2616 Matrix4x4_CreateIdentity(tag_localmatrix);
2619 && (modelindex = (int)e->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2620 && (model = sv.models[(int)e->fields.server->modelindex])
2621 && model->animscenes)
2623 frame = (int)e->fields.server->frame;
2624 if (frame < 0 || frame >= model->numframes)
2627 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)e->fields.server->skin, model->animscenes[frame].firstframe, tagindex - 1, parentindex, tagname, tag_localmatrix);
2638 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2642 float pitchsign = 1;
2647 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2648 if (val && val->_float != 0)
2649 scale = val->_float;
2652 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);
2656 ((modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[(int)ent->fields.server->modelindex]))
2658 model->type == mod_alias
2661 (((unsigned char)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.pflags)->_float) & PFLAGS_FULLDYNAMIC)
2663 ((gamemode == GAME_TENEBRAE) && ((unsigned int)ent->fields.server->effects & (16 | 32)))
2667 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);
2671 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2677 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2678 && (model = sv.models[(int)ent->fields.server->modelindex])
2679 && model->animscenes)
2681 // if model has wrong frame, engine automatically switches to model first frame
2682 frame = (int)ent->fields.server->frame;
2683 if (frame < 0 || frame >= model->numframes)
2685 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2687 *out = identitymatrix;
2691 // Warnings/errors code:
2692 // 0 - normal (everything all-right)
2695 // 3 - null or non-precached model
2696 // 4 - no tags with requested index
2697 // 5 - runaway loop at attachment chain
2698 extern cvar_t cl_bob;
2699 extern cvar_t cl_bobcycle;
2700 extern cvar_t cl_bobup;
2701 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2705 int modelindex, attachloop;
2706 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2709 *out = identitymatrix; // warnings and errors return identical matrix
2711 if (ent == prog->edicts)
2713 if (ent->priv.server->free)
2716 modelindex = (int)ent->fields.server->modelindex;
2717 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2720 model = sv.models[modelindex];
2722 tagmatrix = identitymatrix;
2723 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2727 if (attachloop >= 256) // prevent runaway looping
2729 // apply transformation by child's tagindex on parent entity and then
2730 // by parent entity itself
2731 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2732 if (ret && attachloop == 0)
2734 SV_GetEntityMatrix(ent, &entitymatrix, false);
2735 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2736 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2737 // next iteration we process the parent entity
2738 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2740 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2741 ent = PRVM_EDICT_NUM(val->edict);
2748 // RENDER_VIEWMODEL magic
2749 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2751 Matrix4x4_Copy(&tagmatrix, out);
2752 ent = PRVM_EDICT_NUM(val->edict);
2754 SV_GetEntityMatrix(ent, &entitymatrix, true);
2755 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2758 // Cl_bob, ported from rendering code
2759 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2762 // LordHavoc: this code is *weird*, but not replacable (I think it
2763 // should be done in QC on the server, but oh well, quake is quake)
2764 // LordHavoc: figured out bobup: the time at which the sin is at 180
2765 // degrees (which allows lengthening or squishing the peak or valley)
2766 cycle = sv.time/cl_bobcycle.value;
2767 cycle -= (int)cycle;
2768 if (cycle < cl_bobup.value)
2769 cycle = sin(M_PI * cycle / cl_bobup.value);
2771 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2772 // bob is proportional to velocity in the xy plane
2773 // (don't count Z, or jumping messes it up)
2774 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;
2775 bob = bob*0.3 + bob*0.7*cycle;
2776 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2783 //float(entity ent, string tagname) gettagindex;
2785 static void VM_SV_gettagindex (void)
2788 const char *tag_name;
2789 int modelindex, tag_index;
2791 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2793 ent = PRVM_G_EDICT(OFS_PARM0);
2794 tag_name = PRVM_G_STRING(OFS_PARM1);
2796 if (ent == prog->edicts)
2798 VM_Warning("gettagindex: can't affect world entity\n");
2801 if (ent->priv.server->free)
2803 VM_Warning("gettagindex: can't affect free entity\n");
2807 modelindex = (int)ent->fields.server->modelindex;
2809 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2810 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2813 tag_index = SV_GetTagIndex(ent, tag_name);
2815 if(developer.integer >= 100)
2816 Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2818 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2821 //vector(entity ent, float tagindex) gettaginfo;
2822 static void VM_SV_gettaginfo (void)
2826 matrix4x4_t tag_matrix;
2827 matrix4x4_t tag_localmatrix;
2829 const char *tagname;
2832 vec3_t fo, le, up, trans;
2834 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2836 e = PRVM_G_EDICT(OFS_PARM0);
2837 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2839 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2840 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, le, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2841 VectorScale(le, -1, prog->globals.server->v_right);
2842 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2843 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2845 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_parent)))
2846 val->_float = parentindex;
2847 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_name)))
2848 val->string = tagname ? PRVM_SetTempString(tagname) : 0;
2849 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_offset)))
2850 VectorCopy(trans, val->vector);
2851 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_forward)))
2852 VectorCopy(fo, val->vector);
2853 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_right)))
2854 VectorScale(le, -1, val->vector);
2855 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_up)))
2856 VectorCopy(up, val->vector);
2861 VM_Warning("gettagindex: can't affect world entity\n");
2864 VM_Warning("gettagindex: can't affect free entity\n");
2867 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2870 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2873 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2878 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2879 static void VM_SV_dropclient (void)
2882 client_t *oldhostclient;
2883 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2884 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2885 if (clientnum < 0 || clientnum >= svs.maxclients)
2887 VM_Warning("dropclient: not a client\n");
2890 if (!svs.clients[clientnum].active)
2892 VM_Warning("dropclient: that client slot is not connected\n");
2895 oldhostclient = host_client;
2896 host_client = svs.clients + clientnum;
2897 SV_DropClient(false);
2898 host_client = oldhostclient;
2901 //entity() spawnclient (DP_SV_BOTCLIENT)
2902 static void VM_SV_spawnclient (void)
2906 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2907 prog->xfunction->builtinsprofile += 2;
2909 for (i = 0;i < svs.maxclients;i++)
2911 if (!svs.clients[i].active)
2913 prog->xfunction->builtinsprofile += 100;
2914 SV_ConnectClient (i, NULL);
2915 // this has to be set or else ClientDisconnect won't be called
2916 // we assume the qc will call ClientConnect...
2917 svs.clients[i].clientconnectcalled = true;
2918 ed = PRVM_EDICT_NUM(i + 1);
2922 VM_RETURN_EDICT(ed);
2925 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2926 static void VM_SV_clienttype (void)
2929 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2930 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2931 if (clientnum < 0 || clientnum >= svs.maxclients)
2932 PRVM_G_FLOAT(OFS_RETURN) = 3;
2933 else if (!svs.clients[clientnum].active)
2934 PRVM_G_FLOAT(OFS_RETURN) = 0;
2935 else if (svs.clients[clientnum].netconnection)
2936 PRVM_G_FLOAT(OFS_RETURN) = 1;
2938 PRVM_G_FLOAT(OFS_RETURN) = 2;
2945 string(string key) serverkey
2948 void VM_SV_serverkey(void)
2950 char string[VM_STRINGTEMP_LENGTH];
2951 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2952 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2953 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2956 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2957 static void VM_SV_setmodelindex (void)
2962 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2964 e = PRVM_G_EDICT(OFS_PARM0);
2965 if (e == prog->edicts)
2967 VM_Warning("setmodelindex: can not modify world entity\n");
2970 if (e->priv.server->free)
2972 VM_Warning("setmodelindex: can not modify free entity\n");
2975 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2976 if (i <= 0 || i >= MAX_MODELS)
2978 VM_Warning("setmodelindex: invalid modelindex\n");
2981 if (!sv.model_precache[i][0])
2983 VM_Warning("setmodelindex: model not precached\n");
2987 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2988 e->fields.server->modelindex = i;
2994 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2995 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2997 SetMinMaxSize (e, quakemins, quakemaxs, true);
3000 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
3003 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3004 static void VM_SV_modelnameforindex (void)
3007 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
3009 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
3011 i = (int)PRVM_G_FLOAT(OFS_PARM0);
3012 if (i <= 0 || i >= MAX_MODELS)
3014 VM_Warning("modelnameforindex: invalid modelindex\n");
3017 if (!sv.model_precache[i][0])
3019 VM_Warning("modelnameforindex: model not precached\n");
3023 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
3026 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
3027 static void VM_SV_particleeffectnum (void)
3030 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
3031 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
3034 PRVM_G_FLOAT(OFS_RETURN) = i;
3037 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3038 static void VM_SV_trailparticles (void)
3040 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
3042 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3045 MSG_WriteByte(&sv.datagram, svc_trailparticles);
3046 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
3047 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
3048 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
3049 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
3050 SV_FlushBroadcastMessages();
3053 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
3054 static void VM_SV_pointparticles (void)
3056 int effectnum, count;
3058 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
3060 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3063 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
3064 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
3065 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
3066 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
3067 if (count == 1 && !VectorLength2(vel))
3070 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
3071 MSG_WriteShort(&sv.datagram, effectnum);
3072 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3076 // 1+2+12+12+2=29 bytes
3077 MSG_WriteByte(&sv.datagram, svc_pointparticles);
3078 MSG_WriteShort(&sv.datagram, effectnum);
3079 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3080 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
3081 MSG_WriteShort(&sv.datagram, count);
3084 SV_FlushBroadcastMessages();
3087 //PF_setpause, // void(float pause) setpause = #531;
3088 static void VM_SV_setpause(void) {
3090 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
3091 if (pauseValue != 0) { //pause the game
3093 sv.pausedstart = Sys_DoubleTime();
3094 } else { //disable pause, in case it was enabled
3095 if (sv.paused != 0) {
3100 // send notification to all clients
3101 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
3102 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
3105 prvm_builtin_t vm_sv_builtins[] = {
3106 NULL, // #0 NULL function (not callable) (QUAKE)
3107 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3108 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3109 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3110 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3111 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3112 VM_break, // #6 void() break (QUAKE)
3113 VM_random, // #7 float() random (QUAKE)
3114 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3115 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3116 VM_error, // #10 void(string e) error (QUAKE)
3117 VM_objerror, // #11 void(string e) objerror (QUAKE)
3118 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3119 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3120 VM_spawn, // #14 entity() spawn (QUAKE)
3121 VM_remove, // #15 void(entity e) remove (QUAKE)
3122 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3123 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3124 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3125 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3126 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3127 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3128 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3129 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3130 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3131 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3132 VM_ftos, // #26 string(float f) ftos (QUAKE)
3133 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3134 VM_coredump, // #28 void() coredump (QUAKE)
3135 VM_traceon, // #29 void() traceon (QUAKE)
3136 VM_traceoff, // #30 void() traceoff (QUAKE)
3137 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3138 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3139 NULL, // #33 (QUAKE)
3140 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3141 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3142 VM_rint, // #36 float(float v) rint (QUAKE)
3143 VM_floor, // #37 float(float v) floor (QUAKE)
3144 VM_ceil, // #38 float(float v) ceil (QUAKE)
3145 NULL, // #39 (QUAKE)
3146 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3147 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3148 NULL, // #42 (QUAKE)
3149 VM_fabs, // #43 float(float f) fabs (QUAKE)
3150 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3151 VM_cvar, // #45 float(string s) cvar (QUAKE)
3152 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3153 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3154 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3155 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3156 NULL, // #50 (QUAKE)
3157 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3158 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3159 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3160 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3161 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3162 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3163 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3164 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3165 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3166 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3167 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3168 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3169 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3170 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3171 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3172 NULL, // #66 (QUAKE)
3173 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3174 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3175 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3176 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3177 NULL, // #71 (QUAKE)
3178 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3179 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3180 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3181 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3182 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3183 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3184 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3185 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3186 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3187 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3188 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3189 NULL, // #83 (QUAKE)
3190 NULL, // #84 (QUAKE)
3191 NULL, // #85 (QUAKE)
3192 NULL, // #86 (QUAKE)
3193 NULL, // #87 (QUAKE)
3194 NULL, // #88 (QUAKE)
3195 NULL, // #89 (QUAKE)
3196 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3197 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3198 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3199 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3200 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3201 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3202 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3203 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3204 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3205 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3206 // FrikaC and Telejano range #100-#199
3217 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3218 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3219 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3220 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3221 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3222 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3223 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3224 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3225 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3226 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3307 // FTEQW range #200-#299
3326 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3329 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3330 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3331 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3332 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3333 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3334 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3335 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3336 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3337 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3338 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3340 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3348 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3408 // CSQC range #300-#399
3409 NULL, // #300 void() clearscene (EXT_CSQC)
3410 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3411 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3412 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3413 NULL, // #304 void() renderscene (EXT_CSQC)
3414 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3415 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3416 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3417 NULL, // #308 void() R_EndPolygon
3419 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3420 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3424 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3425 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3426 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3427 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3428 NULL, // #319 void(string name) freepic (EXT_CSQC)
3429 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3430 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3431 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3432 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3433 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3434 NULL, // #325 void(void) drawresetcliparea
3439 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3440 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3441 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3442 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3443 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3444 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3445 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3446 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3447 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3448 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3449 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3450 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3451 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3452 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3453 NULL, // #344 vector() getmousepos (EXT_CSQC)
3454 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3455 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3456 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3457 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3458 NULL, // #349 float() isdemo (EXT_CSQC)
3459 VM_isserver, // #350 float() isserver (EXT_CSQC)
3460 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3461 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3462 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3463 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3469 NULL, // #360 float() readbyte (EXT_CSQC)
3470 NULL, // #361 float() readchar (EXT_CSQC)
3471 NULL, // #362 float() readshort (EXT_CSQC)
3472 NULL, // #363 float() readlong (EXT_CSQC)
3473 NULL, // #364 float() readcoord (EXT_CSQC)
3474 NULL, // #365 float() readangle (EXT_CSQC)
3475 NULL, // #366 string() readstring (EXT_CSQC)
3476 NULL, // #367 float() readfloat (EXT_CSQC)
3509 // LordHavoc's range #400-#499
3510 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3511 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3512 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3513 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3514 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3515 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3516 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3517 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3518 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)
3519 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3520 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3521 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3522 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3523 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3524 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3525 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3526 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3527 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3528 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3529 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3530 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3531 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3532 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3533 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3534 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3535 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3536 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3537 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3538 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3539 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3540 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3541 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3542 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3543 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3544 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3545 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3546 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3547 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3548 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3549 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3550 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3551 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3552 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3553 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3554 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3555 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3556 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3557 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3558 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3559 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3560 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3561 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3562 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3563 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3564 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3565 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3566 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3567 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3569 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3570 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3571 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3572 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3573 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3574 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3575 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3576 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3577 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3578 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3579 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3581 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3582 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3583 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3584 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3585 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3586 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3587 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3588 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3589 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3590 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3591 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3592 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3593 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3594 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3595 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3596 VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3604 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3605 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3606 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3607 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3608 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3609 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3610 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3611 VM_SV_WritePicture, // #501
3613 VM_whichpack, // #503 string(string) whichpack = #503;
3620 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3621 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3622 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3623 VM_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET)
3624 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3625 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3626 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3627 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3628 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3629 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3641 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3734 VM_getextresponse, // #624 string getextresponse(void)
3738 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3740 void VM_SV_Cmd_Init(void)
3745 void VM_SV_Cmd_Reset(void)
3747 if(prog->funcoffsets.SV_Shutdown)
3749 func_t s = prog->funcoffsets.SV_Shutdown;
3750 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3751 PRVM_ExecuteProgram(s,"SV_Shutdown() required");