6 //============================================================================
11 char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
22 "DP_CSQC_MULTIFRAME_INTERPOLATION "
38 "DP_ENT_CUSTOMCOLORMAP "
39 "DP_ENT_EXTERIORMODELTOCLIENT "
42 "DP_ENT_LOWPRECISION "
46 "DP_GFX_EXTERNALTEXTURES "
47 "DP_GFX_EXTERNALTEXTURES_PERMAP "
49 "DP_GFX_QUAKE3MODELTAGS "
52 "DP_GFX_MODEL_INTERPOLATION "
54 "DP_HALFLIFE_MAP_CVAR "
60 "DP_MOVETYPEBOUNCEMISSILE "
63 "DP_QC_ASINACOSATANATAN2TAN "
68 "DP_QC_CVAR_DEFSTRING "
69 "DP_QC_CVAR_DESCRIPTION "
76 "DP_QC_EXTRESPONSEPACKET "
78 "DP_QC_FINDCHAIN_TOFIELD "
79 "DP_QC_FINDCHAINFLAGS "
80 "DP_QC_FINDCHAINFLOAT "
86 "DP_QC_GETSURFACEPOINTATTRIBUTE "
88 "DP_QC_GETTAGINFO_BONEPROPERTIES "
90 "DP_QC_GETTIME_CDTRACK "
93 "DP_QC_MULTIPLETEMPSTRINGS "
94 "DP_QC_NUM_FOR_EDICT "
96 "DP_QC_SINCOSSQRTPOW "
98 "DP_QC_STRINGBUFFERS "
99 "DP_QC_STRINGBUFFERS_CVARLIST "
100 "DP_QC_STRINGCOLORFUNCTIONS "
101 "DP_QC_STRING_CASE_FUNCTIONS "
103 "DP_QC_TOKENIZEBYSEPARATOR "
104 "DP_QC_TOKENIZE_CONSOLE "
107 "DP_QC_TRACE_MOVETYPE_HITMODEL "
108 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
109 "DP_QC_UNLIMITEDTEMPSTRINGS "
112 "DP_QC_VECTOANGLES_WITH_ROLL "
113 "DP_QC_VECTORVECTORS "
120 "DP_SND_DIRECTIONLESSATTNNONE "
128 "DP_SV_BOUNCEFACTOR "
129 "DP_SV_CLIENTCOLORS "
132 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
133 "DP_SV_DRAWONLYTOCLIENT "
136 "DP_SV_ENTITYCONTENTSTRANSITION "
137 "DP_SV_MODELFLAGS_AS_EFFECTS "
138 "DP_SV_MOVETYPESTEP_LANDEVENT "
140 "DP_SV_NODRAWTOCLIENT "
141 "DP_SV_ONENTITYNOSPAWNFUNCTION "
142 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
144 "DP_SV_PLAYERPHYSICS "
145 "DP_SV_POINTPARTICLES "
147 "DP_SV_PRECACHEANYTIME "
151 "DP_SV_ROTATINGBMODEL "
155 "DP_SV_SPAWNFUNC_PREFIX "
156 "DP_SV_WRITEPICTURE "
157 "DP_SV_WRITEUNTERMINATEDSTRING "
161 "DP_TE_EXPLOSIONRGB "
163 "DP_TE_PARTICLECUBE "
164 "DP_TE_PARTICLERAIN "
165 "DP_TE_PARTICLESNOW "
167 "DP_TE_QUADEFFECTS1 "
170 "DP_TE_STANDARDEFFECTBUILTINS "
171 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
173 "DP_LIGHTSTYLE_STATICVALUE "
178 "KRIMZON_SV_PARSECLIENTCOMMAND "
181 "NEXUIZ_PLAYERMODEL "
183 "PRYDON_CLIENTCURSOR "
184 "TENEBRAE_GFX_DLIGHTS "
187 "DP_CSQC_SPAWNPARTICLE "
188 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
189 "DP_CSQC_ENTITYNOCULL "
190 //"EXT_CSQC " // not ready yet
197 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.
199 setorigin (entity, origin)
202 static void VM_SV_setorigin (void)
207 VM_SAFEPARMCOUNT(2, VM_setorigin);
209 e = PRVM_G_EDICT(OFS_PARM0);
210 if (e == prog->edicts)
212 VM_Warning("setorigin: can not modify world entity\n");
215 if (e->priv.server->free)
217 VM_Warning("setorigin: can not modify free entity\n");
220 org = PRVM_G_VECTOR(OFS_PARM1);
221 VectorCopy (org, e->fields.server->origin);
225 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
226 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
230 for (i=0 ; i<3 ; i++)
232 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
234 // set derived values
235 VectorCopy (min, e->fields.server->mins);
236 VectorCopy (max, e->fields.server->maxs);
237 VectorSubtract (max, min, e->fields.server->size);
246 the size box is rotated by the current angle
247 LordHavoc: no it isn't...
249 setsize (entity, minvector, maxvector)
252 static void VM_SV_setsize (void)
257 VM_SAFEPARMCOUNT(3, VM_setsize);
259 e = PRVM_G_EDICT(OFS_PARM0);
260 if (e == prog->edicts)
262 VM_Warning("setsize: can not modify world entity\n");
265 if (e->priv.server->free)
267 VM_Warning("setsize: can not modify free entity\n");
270 min = PRVM_G_VECTOR(OFS_PARM1);
271 max = PRVM_G_VECTOR(OFS_PARM2);
272 SetMinMaxSize (e, min, max, false);
280 setmodel(entity, model)
283 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
284 static void VM_SV_setmodel (void)
290 VM_SAFEPARMCOUNT(2, VM_setmodel);
292 e = PRVM_G_EDICT(OFS_PARM0);
293 if (e == prog->edicts)
295 VM_Warning("setmodel: can not modify world entity\n");
298 if (e->priv.server->free)
300 VM_Warning("setmodel: can not modify free entity\n");
303 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
304 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
305 e->fields.server->modelindex = i;
311 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
312 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
314 SetMinMaxSize (e, quakemins, quakemaxs, true);
317 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
324 single print to a specific client
326 sprint(clientent, value)
329 static void VM_SV_sprint (void)
333 char string[VM_STRINGTEMP_LENGTH];
335 VM_VarString(1, string, sizeof(string));
337 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
339 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
340 // LordHavoc: div0 requested that sprintto world operate like print
347 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
349 VM_Warning("tried to centerprint to a non-client\n");
353 client = svs.clients + entnum-1;
354 if (!client->netconnection)
357 MSG_WriteChar(&client->netconnection->message,svc_print);
358 MSG_WriteString(&client->netconnection->message, string);
366 single print to a specific client
368 centerprint(clientent, value)
371 static void VM_SV_centerprint (void)
375 char string[VM_STRINGTEMP_LENGTH];
377 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
379 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
381 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
383 VM_Warning("tried to centerprint to a non-client\n");
387 client = svs.clients + entnum-1;
388 if (!client->netconnection)
391 VM_VarString(1, string, sizeof(string));
392 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
393 MSG_WriteString(&client->netconnection->message, string);
400 particle(origin, color, count)
403 static void VM_SV_particle (void)
409 VM_SAFEPARMCOUNT(4, VM_SV_particle);
411 org = PRVM_G_VECTOR(OFS_PARM0);
412 dir = PRVM_G_VECTOR(OFS_PARM1);
413 color = PRVM_G_FLOAT(OFS_PARM2);
414 count = PRVM_G_FLOAT(OFS_PARM3);
415 SV_StartParticle (org, dir, (int)color, (int)count);
425 static void VM_SV_ambientsound (void)
429 float vol, attenuation;
432 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
434 pos = PRVM_G_VECTOR (OFS_PARM0);
435 samp = PRVM_G_STRING(OFS_PARM1);
436 vol = PRVM_G_FLOAT(OFS_PARM2);
437 attenuation = PRVM_G_FLOAT(OFS_PARM3);
439 // check to see if samp was properly precached
440 soundnum = SV_SoundIndex(samp, 1);
448 // add an svc_spawnambient command to the level signon packet
451 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
453 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
455 MSG_WriteVector(&sv.signon, pos, sv.protocol);
457 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
458 MSG_WriteShort (&sv.signon, soundnum);
460 MSG_WriteByte (&sv.signon, soundnum);
462 MSG_WriteByte (&sv.signon, (int)(vol*255));
463 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
471 Each entity can have eight independant sound sources, like voice,
474 Channel 0 is an auto-allocate channel, the others override anything
475 already running on that entity/channel pair.
477 An attenuation of 0 will play full volume everywhere in the level.
478 Larger attenuations will drop off.
482 static void VM_SV_sound (void)
486 prvm_edict_t *entity;
490 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
492 entity = PRVM_G_EDICT(OFS_PARM0);
493 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
494 sample = PRVM_G_STRING(OFS_PARM2);
495 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
496 attenuation = PRVM_G_FLOAT(OFS_PARM4);
499 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
503 if (volume < 0 || volume > 255)
505 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
509 if (attenuation < 0 || attenuation > 4)
511 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
515 if (channel < 0 || channel > 7)
517 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
521 SV_StartSound (entity, channel, sample, volume, attenuation);
528 Follows the same logic as VM_SV_sound, except instead of
529 an entity, an origin for the sound is provided, and channel
530 is omitted (since no entity is being tracked).
534 static void VM_SV_pointsound(void)
541 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
543 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
544 sample = PRVM_G_STRING(OFS_PARM1);
545 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
546 attenuation = PRVM_G_FLOAT(OFS_PARM3);
548 if (volume < 0 || volume > 255)
550 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
554 if (attenuation < 0 || attenuation > 4)
556 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
560 SV_StartPointSound (org, sample, volume, attenuation);
567 Used for use tracing and shot targeting
568 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
569 if the tryents flag is set.
571 traceline (vector1, vector2, movetype, ignore)
574 static void VM_SV_traceline (void)
581 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
583 prog->xfunction->builtinsprofile += 30;
585 v1 = PRVM_G_VECTOR(OFS_PARM0);
586 v2 = PRVM_G_VECTOR(OFS_PARM1);
587 move = (int)PRVM_G_FLOAT(OFS_PARM2);
588 ent = PRVM_G_EDICT(OFS_PARM3);
590 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]))
591 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));
593 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
595 VM_SetTraceGlobals(&trace);
603 Used for use tracing and shot targeting
604 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
605 if the tryents flag is set.
607 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
610 // LordHavoc: added this for my own use, VERY useful, similar to traceline
611 static void VM_SV_tracebox (void)
613 float *v1, *v2, *m1, *m2;
618 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
620 prog->xfunction->builtinsprofile += 30;
622 v1 = PRVM_G_VECTOR(OFS_PARM0);
623 m1 = PRVM_G_VECTOR(OFS_PARM1);
624 m2 = PRVM_G_VECTOR(OFS_PARM2);
625 v2 = PRVM_G_VECTOR(OFS_PARM3);
626 move = (int)PRVM_G_FLOAT(OFS_PARM4);
627 ent = PRVM_G_EDICT(OFS_PARM5);
629 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]))
630 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));
632 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
634 VM_SetTraceGlobals(&trace);
637 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
642 vec3_t original_origin;
643 vec3_t original_velocity;
644 vec3_t original_angles;
645 vec3_t original_avelocity;
649 VectorCopy(tossent->fields.server->origin , original_origin );
650 VectorCopy(tossent->fields.server->velocity , original_velocity );
651 VectorCopy(tossent->fields.server->angles , original_angles );
652 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
654 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
655 if (val != NULL && val->_float != 0)
656 gravity = val->_float;
659 gravity *= sv_gravity.value * 0.025;
661 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
663 SV_CheckVelocity (tossent);
664 tossent->fields.server->velocity[2] -= gravity;
665 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
666 VectorScale (tossent->fields.server->velocity, 0.05, move);
667 VectorAdd (tossent->fields.server->origin, move, end);
668 trace = SV_TraceBox(tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
669 VectorCopy (trace.endpos, tossent->fields.server->origin);
670 tossent->fields.server->velocity[2] -= gravity;
672 if (trace.fraction < 1)
676 VectorCopy(original_origin , tossent->fields.server->origin );
677 VectorCopy(original_velocity , tossent->fields.server->velocity );
678 VectorCopy(original_angles , tossent->fields.server->angles );
679 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
684 static void VM_SV_tracetoss (void)
688 prvm_edict_t *ignore;
690 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
692 prog->xfunction->builtinsprofile += 600;
694 ent = PRVM_G_EDICT(OFS_PARM0);
695 if (ent == prog->edicts)
697 VM_Warning("tracetoss: can not use world entity\n");
700 ignore = PRVM_G_EDICT(OFS_PARM1);
702 trace = SV_Trace_Toss (ent, ignore);
704 VM_SetTraceGlobals(&trace);
707 //============================================================================
709 static int checkpvsbytes;
710 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
712 static int VM_SV_newcheckclient (int check)
718 // cycle to the next one
720 check = bound(1, check, svs.maxclients);
721 if (check == svs.maxclients)
729 prog->xfunction->builtinsprofile++;
731 if (i == svs.maxclients+1)
733 // look up the client's edict
734 ent = PRVM_EDICT_NUM(i);
735 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
736 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
738 // found a valid client (possibly the same one again)
742 // get the PVS for the entity
743 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
745 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
746 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
755 Returns a client (or object that has a client enemy) that would be a
758 If there is more than one valid option, they are cycled each frame
760 If (self.origin + self.viewofs) is not in the PVS of the current target,
761 it is not returned at all.
766 int c_invis, c_notvis;
767 static void VM_SV_checkclient (void)
769 prvm_edict_t *ent, *self;
772 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
774 // find a new check if on a new frame
775 if (sv.time - sv.lastchecktime >= 0.1)
777 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
778 sv.lastchecktime = sv.time;
781 // return check if it might be visible
782 ent = PRVM_EDICT_NUM(sv.lastcheck);
783 if (ent->priv.server->free || ent->fields.server->health <= 0)
785 VM_RETURN_EDICT(prog->edicts);
789 // if current entity can't possibly see the check entity, return 0
790 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
791 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
792 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
795 VM_RETURN_EDICT(prog->edicts);
799 // might be able to see it
801 VM_RETURN_EDICT(ent);
804 //============================================================================
810 Checks if an entity is in a point's PVS.
811 Should be fast but can be inexact.
813 float checkpvs(vector viewpos, entity viewee) = #240;
816 static void VM_SV_checkpvs (void)
819 prvm_edict_t *viewee;
824 unsigned char fatpvs[MAX_MAP_LEAFS/8];
827 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
828 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
829 viewee = PRVM_G_EDICT(OFS_PARM1);
831 if(viewee->priv.server->free)
833 VM_Warning("checkpvs: can not check free entity\n");
834 PRVM_G_FLOAT(OFS_RETURN) = 4;
839 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
841 // no PVS support on this worldmodel... darn
842 PRVM_G_FLOAT(OFS_RETURN) = 3;
845 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
848 // viewpos isn't in any PVS... darn
849 PRVM_G_FLOAT(OFS_RETURN) = 2;
852 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
854 // using fat PVS like FTEQW does (slow)
855 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
857 // no PVS support on this worldmodel... darn
858 PRVM_G_FLOAT(OFS_RETURN) = 3;
861 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
864 // viewpos isn't in any PVS... darn
865 PRVM_G_FLOAT(OFS_RETURN) = 2;
868 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
877 Sends text over to the client's execution buffer
879 stuffcmd (clientent, value, ...)
882 static void VM_SV_stuffcmd (void)
886 char string[VM_STRINGTEMP_LENGTH];
888 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
890 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
891 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
893 VM_Warning("Can't stuffcmd to a non-client\n");
897 VM_VarString(1, string, sizeof(string));
900 host_client = svs.clients + entnum-1;
901 Host_ClientCommands ("%s", string);
909 Returns a chain of entities that have origins within a spherical area
911 findradius (origin, radius)
914 static void VM_SV_findradius (void)
916 prvm_edict_t *ent, *chain;
917 vec_t radius, radius2;
918 vec3_t org, eorg, mins, maxs;
921 prvm_edict_t *touchedicts[MAX_EDICTS];
924 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
927 chainfield = PRVM_G_INT(OFS_PARM2);
929 chainfield = prog->fieldoffsets.chain;
931 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
933 chain = (prvm_edict_t *)prog->edicts;
935 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
936 radius = PRVM_G_FLOAT(OFS_PARM1);
937 radius2 = radius * radius;
939 mins[0] = org[0] - (radius + 1);
940 mins[1] = org[1] - (radius + 1);
941 mins[2] = org[2] - (radius + 1);
942 maxs[0] = org[0] + (radius + 1);
943 maxs[1] = org[1] + (radius + 1);
944 maxs[2] = org[2] + (radius + 1);
945 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
946 if (numtouchedicts > MAX_EDICTS)
948 // this never happens
949 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
950 numtouchedicts = MAX_EDICTS;
952 for (i = 0;i < numtouchedicts;i++)
954 ent = touchedicts[i];
955 prog->xfunction->builtinsprofile++;
956 // Quake did not return non-solid entities but darkplaces does
957 // (note: this is the reason you can't blow up fallen zombies)
958 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
960 // LordHavoc: compare against bounding box rather than center so it
961 // doesn't miss large objects, and use DotProduct instead of Length
962 // for a major speedup
963 VectorSubtract(org, ent->fields.server->origin, eorg);
964 if (sv_gameplayfix_findradiusdistancetobox.integer)
966 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
967 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
968 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
971 VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
972 if (DotProduct(eorg, eorg) < radius2)
974 PRVM_EDICTFIELDVALUE(ent,chainfield)->edict = PRVM_EDICT_TO_PROG(chain);
979 VM_RETURN_EDICT(chain);
982 static void VM_SV_precache_sound (void)
984 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
985 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
988 static void VM_SV_precache_model (void)
990 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
991 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
992 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
999 float(float yaw, float dist[, settrace]) walkmove
1002 static void VM_SV_walkmove (void)
1011 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1013 // assume failure if it returns early
1014 PRVM_G_FLOAT(OFS_RETURN) = 0;
1016 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1017 if (ent == prog->edicts)
1019 VM_Warning("walkmove: can not modify world entity\n");
1022 if (ent->priv.server->free)
1024 VM_Warning("walkmove: can not modify free entity\n");
1027 yaw = PRVM_G_FLOAT(OFS_PARM0);
1028 dist = PRVM_G_FLOAT(OFS_PARM1);
1029 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1031 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1034 yaw = yaw*M_PI*2 / 360;
1036 move[0] = cos(yaw)*dist;
1037 move[1] = sin(yaw)*dist;
1040 // save program state, because SV_movestep may call other progs
1041 oldf = prog->xfunction;
1042 oldself = prog->globals.server->self;
1044 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1047 // restore program state
1048 prog->xfunction = oldf;
1049 prog->globals.server->self = oldself;
1059 static void VM_SV_droptofloor (void)
1065 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1067 // assume failure if it returns early
1068 PRVM_G_FLOAT(OFS_RETURN) = 0;
1070 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1071 if (ent == prog->edicts)
1073 VM_Warning("droptofloor: can not modify world entity\n");
1076 if (ent->priv.server->free)
1078 VM_Warning("droptofloor: can not modify free entity\n");
1082 VectorCopy (ent->fields.server->origin, end);
1085 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1086 SV_UnstickEntity(ent);
1088 trace = SV_TraceBox(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1089 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1092 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]);
1093 VectorAdd(ent->fields.server->origin, offset, org);
1094 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1095 VectorSubtract(trace.endpos, offset, trace.endpos);
1096 if (trace.startsolid)
1098 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]);
1099 SV_UnstickEntity(ent);
1101 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1102 ent->fields.server->groundentity = 0;
1103 PRVM_G_FLOAT(OFS_RETURN) = 1;
1105 else if (trace.fraction < 1)
1107 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]);
1108 VectorCopy (trace.endpos, ent->fields.server->origin);
1109 SV_UnstickEntity(ent);
1111 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1112 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1113 PRVM_G_FLOAT(OFS_RETURN) = 1;
1114 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1115 ent->priv.server->suspendedinairflag = true;
1120 if (trace.fraction != 1)
1122 if (trace.fraction < 1)
1123 VectorCopy (trace.endpos, ent->fields.server->origin);
1125 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1126 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1127 PRVM_G_FLOAT(OFS_RETURN) = 1;
1128 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1129 ent->priv.server->suspendedinairflag = true;
1138 void(float style, string value) lightstyle
1141 static void VM_SV_lightstyle (void)
1148 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1150 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1151 val = PRVM_G_STRING(OFS_PARM1);
1153 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1154 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1157 // change the string in sv
1158 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1160 // send message to all clients on this server
1161 if (sv.state != ss_active)
1164 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1166 if (client->active && client->netconnection)
1168 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1169 MSG_WriteChar (&client->netconnection->message,style);
1170 MSG_WriteString (&client->netconnection->message, val);
1180 static void VM_SV_checkbottom (void)
1182 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1183 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1191 static void VM_SV_pointcontents (void)
1193 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1194 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1201 Pick a vector for the player to shoot along
1202 vector aim(entity, missilespeed)
1205 static void VM_SV_aim (void)
1207 prvm_edict_t *ent, *check, *bestent;
1208 vec3_t start, dir, end, bestdir;
1211 float dist, bestdist;
1214 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1216 // assume failure if it returns early
1217 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1218 // if sv_aim is so high it can't possibly accept anything, skip out early
1219 if (sv_aim.value >= 1)
1222 ent = PRVM_G_EDICT(OFS_PARM0);
1223 if (ent == prog->edicts)
1225 VM_Warning("aim: can not use world entity\n");
1228 if (ent->priv.server->free)
1230 VM_Warning("aim: can not use free entity\n");
1233 speed = PRVM_G_FLOAT(OFS_PARM1);
1235 VectorCopy (ent->fields.server->origin, start);
1238 // try sending a trace straight
1239 VectorCopy (prog->globals.server->v_forward, dir);
1240 VectorMA (start, 2048, dir, end);
1241 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1242 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1243 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1245 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1250 // try all possible entities
1251 VectorCopy (dir, bestdir);
1252 bestdist = sv_aim.value;
1255 check = PRVM_NEXT_EDICT(prog->edicts);
1256 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1258 prog->xfunction->builtinsprofile++;
1259 if (check->fields.server->takedamage != DAMAGE_AIM)
1263 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1264 continue; // don't aim at teammate
1265 for (j=0 ; j<3 ; j++)
1266 end[j] = check->fields.server->origin[j]
1267 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1268 VectorSubtract (end, start, dir);
1269 VectorNormalize (dir);
1270 dist = DotProduct (dir, prog->globals.server->v_forward);
1271 if (dist < bestdist)
1272 continue; // to far to turn
1273 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1274 if (tr.ent == check)
1275 { // can shoot at this one
1283 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1284 dist = DotProduct (dir, prog->globals.server->v_forward);
1285 VectorScale (prog->globals.server->v_forward, dist, end);
1287 VectorNormalize (end);
1288 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1292 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1297 ===============================================================================
1301 ===============================================================================
1304 #define MSG_BROADCAST 0 // unreliable to all
1305 #define MSG_ONE 1 // reliable to one (msg_entity)
1306 #define MSG_ALL 2 // reliable to all
1307 #define MSG_INIT 3 // write to the init string
1308 #define MSG_ENTITY 5
1310 sizebuf_t *WriteDest (void)
1316 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1320 return &sv.datagram;
1323 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1324 entnum = PRVM_NUM_FOR_EDICT(ent);
1325 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1327 VM_Warning ("WriteDest: tried to write to non-client\n");
1328 return &sv.reliable_datagram;
1331 return &svs.clients[entnum-1].netconnection->message;
1334 VM_Warning ("WriteDest: bad destination\n");
1336 return &sv.reliable_datagram;
1342 return sv.writeentitiestoclient_msg;
1348 static void VM_SV_WriteByte (void)
1350 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1351 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1354 static void VM_SV_WriteChar (void)
1356 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1357 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1360 static void VM_SV_WriteShort (void)
1362 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1363 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1366 static void VM_SV_WriteLong (void)
1368 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1369 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1372 static void VM_SV_WriteAngle (void)
1374 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1375 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1378 static void VM_SV_WriteCoord (void)
1380 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1381 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1384 static void VM_SV_WriteString (void)
1386 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1387 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1390 static void VM_SV_WriteUnterminatedString (void)
1392 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1393 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1397 static void VM_SV_WriteEntity (void)
1399 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1400 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1403 // writes a picture as at most size bytes of data
1405 // IMGNAME \0 SIZE(short) IMGDATA
1406 // if failed to read/compress:
1408 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1409 static void VM_SV_WritePicture (void)
1411 const char *imgname;
1415 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1417 imgname = PRVM_G_STRING(OFS_PARM1);
1418 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1422 MSG_WriteString(WriteDest(), imgname);
1423 if(Image_Compress(imgname, size, &buf, &size))
1426 MSG_WriteShort(WriteDest(), size);
1427 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1432 MSG_WriteShort(WriteDest(), 0);
1436 //////////////////////////////////////////////////////////
1438 static void VM_SV_makestatic (void)
1443 // allow 0 parameters due to an id1 qc bug in which this function is used
1444 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1445 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1447 if (prog->argc >= 1)
1448 ent = PRVM_G_EDICT(OFS_PARM0);
1450 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1451 if (ent == prog->edicts)
1453 VM_Warning("makestatic: can not modify world entity\n");
1456 if (ent->priv.server->free)
1458 VM_Warning("makestatic: can not modify free entity\n");
1463 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1468 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1469 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1470 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1472 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1474 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1475 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1476 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1480 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1481 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1482 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1485 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1486 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1487 for (i=0 ; i<3 ; i++)
1489 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1490 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1493 // throw the entity away now
1497 //=============================================================================
1504 static void VM_SV_setspawnparms (void)
1510 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1512 ent = PRVM_G_EDICT(OFS_PARM0);
1513 i = PRVM_NUM_FOR_EDICT(ent);
1514 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1516 Con_Print("tried to setspawnparms on a non-client\n");
1520 // copy spawn parms out of the client_t
1521 client = svs.clients + i-1;
1522 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1523 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1530 Returns a color vector indicating the lighting at the requested point.
1532 (Internal Operation note: actually measures the light beneath the point, just like
1533 the model lighting on the client)
1538 static void VM_SV_getlight (void)
1540 vec3_t ambientcolor, diffusecolor, diffusenormal;
1542 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1543 p = PRVM_G_VECTOR(OFS_PARM0);
1544 VectorClear(ambientcolor);
1545 VectorClear(diffusecolor);
1546 VectorClear(diffusenormal);
1547 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1548 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1549 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1554 unsigned char type; // 1/2/8 or other value if isn't used
1558 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1559 static int vm_customstats_last;
1561 void VM_CustomStats_Clear (void)
1565 Z_Free(vm_customstats);
1566 vm_customstats = NULL;
1567 vm_customstats_last = -1;
1571 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1579 for(i=0; i<vm_customstats_last+1 ;i++)
1581 if(!vm_customstats[i].type)
1583 switch(vm_customstats[i].type)
1585 //string as 16 bytes
1588 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1589 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1590 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1591 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1592 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1594 //float field sent as-is
1596 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1598 //integer value of float field
1600 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1608 // void(float index, float type, .void field) SV_AddStat = #232;
1609 // Set up an auto-sent player stat.
1610 // Client's get thier own fields sent to them. Index may not be less than 32.
1611 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1612 // 1: string (4 stats carrying a total of 16 charactures)
1613 // 2: float (one stat, float converted to an integer for transportation)
1614 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1615 static void VM_SV_AddStat (void)
1620 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1624 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1627 VM_Warning("PF_SV_AddStat: not enough memory\n");
1631 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1632 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1633 off = PRVM_G_INT (OFS_PARM2);
1638 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1641 if(i >= (MAX_CL_STATS-32))
1643 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1646 if(i > (MAX_CL_STATS-32-4) && type == 1)
1648 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1651 vm_customstats[i].type = type;
1652 vm_customstats[i].fieldoffset = off;
1653 if(vm_customstats_last < i)
1654 vm_customstats_last = i;
1661 copies data from one entity to another
1663 copyentity(src, dst)
1666 static void VM_SV_copyentity (void)
1668 prvm_edict_t *in, *out;
1669 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1670 in = PRVM_G_EDICT(OFS_PARM0);
1671 if (in == prog->edicts)
1673 VM_Warning("copyentity: can not read world entity\n");
1676 if (in->priv.server->free)
1678 VM_Warning("copyentity: can not read free entity\n");
1681 out = PRVM_G_EDICT(OFS_PARM1);
1682 if (out == prog->edicts)
1684 VM_Warning("copyentity: can not modify world entity\n");
1687 if (out->priv.server->free)
1689 VM_Warning("copyentity: can not modify free entity\n");
1692 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1701 sets the color of a client and broadcasts the update to all connected clients
1703 setcolor(clientent, value)
1706 static void VM_SV_setcolor (void)
1712 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1713 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1714 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1716 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1718 Con_Print("tried to setcolor a non-client\n");
1722 client = svs.clients + entnum-1;
1725 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1727 client->edict->fields.server->team = (i & 15) + 1;
1730 if (client->old_colors != client->colors)
1732 client->old_colors = client->colors;
1733 // send notification to all clients
1734 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1735 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1736 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1744 effect(origin, modelname, startframe, framecount, framerate)
1747 static void VM_SV_effect (void)
1751 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1752 s = PRVM_G_STRING(OFS_PARM1);
1755 VM_Warning("effect: no model specified\n");
1759 i = SV_ModelIndex(s, 1);
1762 VM_Warning("effect: model not precached\n");
1766 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1768 VM_Warning("effect: framecount < 1\n");
1772 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1774 VM_Warning("effect: framerate < 1\n");
1778 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));
1781 static void VM_SV_te_blood (void)
1783 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1784 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1786 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1787 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1789 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1790 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1791 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1793 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1794 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1795 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1797 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1798 SV_FlushBroadcastMessages();
1801 static void VM_SV_te_bloodshower (void)
1803 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1804 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1806 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1807 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1809 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1810 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1813 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1814 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1815 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1817 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1819 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1820 SV_FlushBroadcastMessages();
1823 static void VM_SV_te_explosionrgb (void)
1825 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1826 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1827 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1830 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1831 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1833 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1834 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1835 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1836 SV_FlushBroadcastMessages();
1839 static void VM_SV_te_particlecube (void)
1841 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1842 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1844 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1845 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1847 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1848 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1849 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1851 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1852 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1853 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1855 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1856 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1857 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1859 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1861 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1862 // gravity true/false
1863 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1865 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1866 SV_FlushBroadcastMessages();
1869 static void VM_SV_te_particlerain (void)
1871 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1872 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1874 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1875 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1877 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1878 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1879 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1881 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1882 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1883 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1885 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1886 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1887 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1889 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1891 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1892 SV_FlushBroadcastMessages();
1895 static void VM_SV_te_particlesnow (void)
1897 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1898 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1900 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1901 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1911 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1912 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1913 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1915 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1917 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1918 SV_FlushBroadcastMessages();
1921 static void VM_SV_te_spark (void)
1923 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1924 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1926 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1927 MSG_WriteByte(&sv.datagram, TE_SPARK);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1933 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1934 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1935 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1937 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1938 SV_FlushBroadcastMessages();
1941 static void VM_SV_te_gunshotquad (void)
1943 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1944 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1945 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1948 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1949 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1950 SV_FlushBroadcastMessages();
1953 static void VM_SV_te_spikequad (void)
1955 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1956 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1957 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1962 SV_FlushBroadcastMessages();
1965 static void VM_SV_te_superspikequad (void)
1967 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1968 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1969 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1972 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1973 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1974 SV_FlushBroadcastMessages();
1977 static void VM_SV_te_explosionquad (void)
1979 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
1980 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1981 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1983 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1984 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1985 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1986 SV_FlushBroadcastMessages();
1989 static void VM_SV_te_smallflash (void)
1991 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
1992 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1993 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1995 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1996 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1997 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1998 SV_FlushBroadcastMessages();
2001 static void VM_SV_te_customflash (void)
2003 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2004 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2006 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2007 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2009 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2010 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2011 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2013 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2015 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2017 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2018 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2019 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2020 SV_FlushBroadcastMessages();
2023 static void VM_SV_te_gunshot (void)
2025 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2026 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2027 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2029 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2030 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2031 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2032 SV_FlushBroadcastMessages();
2035 static void VM_SV_te_spike (void)
2037 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2038 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2039 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2041 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2042 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2043 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2044 SV_FlushBroadcastMessages();
2047 static void VM_SV_te_superspike (void)
2049 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2050 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2051 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2054 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2055 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2056 SV_FlushBroadcastMessages();
2059 static void VM_SV_te_explosion (void)
2061 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2062 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2063 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2065 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2066 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2067 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2068 SV_FlushBroadcastMessages();
2071 static void VM_SV_te_tarexplosion (void)
2073 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2074 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2075 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2077 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2078 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2079 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2080 SV_FlushBroadcastMessages();
2083 static void VM_SV_te_wizspike (void)
2085 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2086 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2087 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2089 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2090 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2091 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2092 SV_FlushBroadcastMessages();
2095 static void VM_SV_te_knightspike (void)
2097 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2098 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2099 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2101 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2102 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2103 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2104 SV_FlushBroadcastMessages();
2107 static void VM_SV_te_lavasplash (void)
2109 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2110 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2111 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2113 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2114 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2115 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2116 SV_FlushBroadcastMessages();
2119 static void VM_SV_te_teleport (void)
2121 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2122 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2123 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2125 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2126 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2127 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2128 SV_FlushBroadcastMessages();
2131 static void VM_SV_te_explosion2 (void)
2133 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2134 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2135 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2137 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2138 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2139 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2141 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2142 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2143 SV_FlushBroadcastMessages();
2146 static void VM_SV_te_lightning1 (void)
2148 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2149 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2150 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2152 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2154 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2155 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2156 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2158 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2159 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2160 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2161 SV_FlushBroadcastMessages();
2164 static void VM_SV_te_lightning2 (void)
2166 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2167 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2168 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2170 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2172 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2173 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2174 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2176 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2177 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2178 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2179 SV_FlushBroadcastMessages();
2182 static void VM_SV_te_lightning3 (void)
2184 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2185 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2186 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2188 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2190 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2191 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2192 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2194 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2195 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2196 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2197 SV_FlushBroadcastMessages();
2200 static void VM_SV_te_beam (void)
2202 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2203 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2204 MSG_WriteByte(&sv.datagram, TE_BEAM);
2206 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2208 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2209 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2210 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2212 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2213 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2214 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2215 SV_FlushBroadcastMessages();
2218 static void VM_SV_te_plasmaburn (void)
2220 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2221 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2222 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2223 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2224 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2225 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2226 SV_FlushBroadcastMessages();
2229 static void VM_SV_te_flamejet (void)
2231 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2232 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2233 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2235 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2236 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2237 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2239 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2240 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2241 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2243 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2244 SV_FlushBroadcastMessages();
2247 void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2250 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2252 bestdist = 1000000000;
2254 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2256 // clip original point to each triangle of the surface and find the
2257 // triangle that is closest
2258 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2259 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2260 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2261 TriangleNormal(v[0], v[1], v[2], facenormal);
2262 VectorNormalize(facenormal);
2263 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2264 VectorMA(p, offsetdist, facenormal, temp);
2265 for (j = 0, k = 2;j < 3;k = j, j++)
2267 VectorSubtract(v[k], v[j], edgenormal);
2268 CrossProduct(edgenormal, facenormal, sidenormal);
2269 VectorNormalize(sidenormal);
2270 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2272 VectorMA(temp, offsetdist, sidenormal, temp);
2274 dist = VectorDistance2(temp, p);
2275 if (bestdist > dist)
2278 VectorCopy(temp, out);
2283 static dp_model_t *getmodel(prvm_edict_t *ed)
2286 if (!ed || ed->priv.server->free)
2288 modelindex = (int)ed->fields.server->modelindex;
2289 if (modelindex < 1 || modelindex >= MAX_MODELS)
2291 return sv.models[modelindex];
2294 static msurface_t *getsurface(dp_model_t *model, int surfacenum)
2296 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2298 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2302 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2303 static void VM_SV_getsurfacenumpoints(void)
2306 msurface_t *surface;
2307 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints);
2308 // return 0 if no such surface
2309 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2311 PRVM_G_FLOAT(OFS_RETURN) = 0;
2315 // note: this (incorrectly) assumes it is a simple polygon
2316 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2318 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2319 static void VM_SV_getsurfacepoint(void)
2323 msurface_t *surface;
2325 VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint);
2326 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2327 ed = PRVM_G_EDICT(OFS_PARM0);
2328 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2330 // note: this (incorrectly) assumes it is a simple polygon
2331 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2332 if (pointnum < 0 || pointnum >= surface->num_vertices)
2334 // FIXME: implement rotation/scaling
2335 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2337 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
2338 // float SPA_POSITION = 0;
2339 // float SPA_S_AXIS = 1;
2340 // float SPA_T_AXIS = 2;
2341 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2342 // float SPA_TEXCOORDS0 = 4;
2343 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2344 // float SPA_LIGHTMAP0_COLOR = 6;
2345 static void VM_SV_getsurfacepointattribute(void)
2349 msurface_t *surface;
2353 VM_SAFEPARMCOUNT(4, VM_SV_getsurfacepoint);
2354 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2355 ed = PRVM_G_EDICT(OFS_PARM0);
2356 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2358 // note: this (incorrectly) assumes it is a simple polygon
2359 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2360 if (pointnum < 0 || pointnum >= surface->num_vertices)
2362 // FIXME: implement rotation/scaling
2363 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
2365 switch( attributetype ) {
2366 // float SPA_POSITION = 0;
2368 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2370 // float SPA_S_AXIS = 1;
2372 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2374 // float SPA_T_AXIS = 2;
2376 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2378 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2380 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2382 // float SPA_TEXCOORDS0 = 4;
2384 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2385 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
2386 ret[0] = texcoord[0];
2387 ret[1] = texcoord[1];
2391 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2393 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2394 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
2395 ret[0] = texcoord[0];
2396 ret[1] = texcoord[1];
2400 // float SPA_LIGHTMAP0_COLOR = 6;
2402 // ignore alpha for now..
2403 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2406 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2410 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2411 static void VM_SV_getsurfacenormal(void)
2414 msurface_t *surface;
2416 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal);
2417 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2418 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2420 // FIXME: implement rotation/scaling
2421 // note: this (incorrectly) assumes it is a simple polygon
2422 // note: this only returns the first triangle, so it doesn't work very
2423 // well for curved surfaces or arbitrary meshes
2424 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);
2425 VectorNormalize(normal);
2426 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2428 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2429 static void VM_SV_getsurfacetexture(void)
2432 msurface_t *surface;
2433 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture);
2434 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2435 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2437 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2439 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2440 static void VM_SV_getsurfacenearpoint(void)
2442 int surfacenum, best;
2444 vec_t dist, bestdist;
2447 msurface_t *surface;
2449 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint);
2450 PRVM_G_FLOAT(OFS_RETURN) = -1;
2451 ed = PRVM_G_EDICT(OFS_PARM0);
2452 point = PRVM_G_VECTOR(OFS_PARM1);
2454 if (!ed || ed->priv.server->free)
2456 model = getmodel(ed);
2457 if (!model || !model->num_surfaces)
2460 // FIXME: implement rotation/scaling
2461 VectorSubtract(point, ed->fields.server->origin, p);
2463 bestdist = 1000000000;
2464 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2466 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2467 // first see if the nearest point on the surface's box is closer than the previous match
2468 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2469 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2470 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2471 dist = VectorLength2(clipped);
2472 if (dist < bestdist)
2474 // it is, check the nearest point on the actual geometry
2475 clippointtosurface(model, surface, p, clipped);
2476 VectorSubtract(clipped, p, clipped);
2477 dist += VectorLength2(clipped);
2478 if (dist < bestdist)
2480 // that's closer too, store it as the best match
2486 PRVM_G_FLOAT(OFS_RETURN) = best;
2488 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2489 static void VM_SV_getsurfaceclippedpoint(void)
2493 msurface_t *surface;
2495 VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint);
2496 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2497 ed = PRVM_G_EDICT(OFS_PARM0);
2498 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2500 // FIXME: implement rotation/scaling
2501 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2502 clippointtosurface(model, surface, p, out);
2503 // FIXME: implement rotation/scaling
2504 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2507 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2508 //this function originally written by KrimZon, made shorter by LordHavoc
2509 static void VM_SV_clientcommand (void)
2511 client_t *temp_client;
2513 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2515 //find client for this entity
2516 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2517 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2519 Con_Print("PF_clientcommand: entity is not a client\n");
2523 temp_client = host_client;
2524 host_client = svs.clients + i;
2525 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2526 host_client = temp_client;
2529 //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)
2530 static void VM_SV_setattachment (void)
2532 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2533 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2534 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2538 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2540 if (e == prog->edicts)
2542 VM_Warning("setattachment: can not modify world entity\n");
2545 if (e->priv.server->free)
2547 VM_Warning("setattachment: can not modify free entity\n");
2551 if (tagentity == NULL)
2552 tagentity = prog->edicts;
2554 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2556 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2558 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2561 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2563 modelindex = (int)tagentity->fields.server->modelindex;
2564 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2566 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2568 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);
2571 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));
2575 /////////////////////////////////////////
2576 // DP_MD3_TAGINFO extension coded by VorteX
2578 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2583 i = (int)e->fields.server->modelindex;
2584 if (i < 1 || i >= MAX_MODELS)
2586 model = sv.models[i];
2588 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2591 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2600 Matrix4x4_CreateIdentity(tag_localmatrix);
2603 && (modelindex = (int)e->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2604 && (model = sv.models[(int)e->fields.server->modelindex])
2605 && model->animscenes)
2607 frame = (int)e->fields.server->frame;
2608 if (frame < 0 || frame >= model->numframes)
2611 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)e->fields.server->skin, model->animscenes[frame].firstframe, tagindex - 1, parentindex, tagname, tag_localmatrix);
2622 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2626 float pitchsign = 1;
2629 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2630 if (val && val->_float != 0)
2631 scale = val->_float;
2634 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);
2637 pitchsign = SV_GetPitchSign(ent);
2638 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);
2642 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2648 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2649 && (model = sv.models[(int)ent->fields.server->modelindex])
2650 && model->animscenes)
2652 // if model has wrong frame, engine automatically switches to model first frame
2653 frame = (int)ent->fields.server->frame;
2654 if (frame < 0 || frame >= model->numframes)
2656 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2658 *out = identitymatrix;
2662 // Warnings/errors code:
2663 // 0 - normal (everything all-right)
2666 // 3 - null or non-precached model
2667 // 4 - no tags with requested index
2668 // 5 - runaway loop at attachment chain
2669 extern cvar_t cl_bob;
2670 extern cvar_t cl_bobcycle;
2671 extern cvar_t cl_bobup;
2672 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2676 int modelindex, attachloop;
2677 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2680 *out = identitymatrix; // warnings and errors return identical matrix
2682 if (ent == prog->edicts)
2684 if (ent->priv.server->free)
2687 modelindex = (int)ent->fields.server->modelindex;
2688 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2691 model = sv.models[modelindex];
2693 tagmatrix = identitymatrix;
2694 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2698 if (attachloop >= 256) // prevent runaway looping
2700 // apply transformation by child's tagindex on parent entity and then
2701 // by parent entity itself
2702 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2703 if (ret && attachloop == 0)
2705 SV_GetEntityMatrix(ent, &entitymatrix, false);
2706 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2707 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2708 // next iteration we process the parent entity
2709 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2711 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2712 ent = PRVM_EDICT_NUM(val->edict);
2719 // RENDER_VIEWMODEL magic
2720 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2722 Matrix4x4_Copy(&tagmatrix, out);
2723 ent = PRVM_EDICT_NUM(val->edict);
2725 SV_GetEntityMatrix(ent, &entitymatrix, true);
2726 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2729 // Cl_bob, ported from rendering code
2730 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2733 // LordHavoc: this code is *weird*, but not replacable (I think it
2734 // should be done in QC on the server, but oh well, quake is quake)
2735 // LordHavoc: figured out bobup: the time at which the sin is at 180
2736 // degrees (which allows lengthening or squishing the peak or valley)
2737 cycle = sv.time/cl_bobcycle.value;
2738 cycle -= (int)cycle;
2739 if (cycle < cl_bobup.value)
2740 cycle = sin(M_PI * cycle / cl_bobup.value);
2742 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2743 // bob is proportional to velocity in the xy plane
2744 // (don't count Z, or jumping messes it up)
2745 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;
2746 bob = bob*0.3 + bob*0.7*cycle;
2747 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2754 //float(entity ent, string tagname) gettagindex;
2756 static void VM_SV_gettagindex (void)
2759 const char *tag_name;
2760 int modelindex, tag_index;
2762 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2764 ent = PRVM_G_EDICT(OFS_PARM0);
2765 tag_name = PRVM_G_STRING(OFS_PARM1);
2767 if (ent == prog->edicts)
2769 VM_Warning("gettagindex: can't affect world entity\n");
2772 if (ent->priv.server->free)
2774 VM_Warning("gettagindex: can't affect free entity\n");
2778 modelindex = (int)ent->fields.server->modelindex;
2780 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2781 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2784 tag_index = SV_GetTagIndex(ent, tag_name);
2786 if(developer.integer >= 100)
2787 Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2789 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2792 //vector(entity ent, float tagindex) gettaginfo;
2793 static void VM_SV_gettaginfo (void)
2797 matrix4x4_t tag_matrix;
2798 matrix4x4_t tag_localmatrix;
2800 const char *tagname;
2803 vec3_t fo, le, up, trans;
2805 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2807 e = PRVM_G_EDICT(OFS_PARM0);
2808 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2810 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2811 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, le, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2812 VectorScale(le, -1, prog->globals.server->v_right);
2813 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2814 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2816 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_parent)))
2817 val->_float = parentindex;
2818 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_name)))
2819 val->string = tagname ? PRVM_SetTempString(tagname) : 0;
2820 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_offset)))
2821 VectorCopy(trans, val->vector);
2822 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_forward)))
2823 VectorCopy(fo, val->vector);
2824 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_right)))
2825 VectorScale(le, -1, val->vector);
2826 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_up)))
2827 VectorCopy(up, val->vector);
2832 VM_Warning("gettagindex: can't affect world entity\n");
2835 VM_Warning("gettagindex: can't affect free entity\n");
2838 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2841 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2844 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2849 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2850 static void VM_SV_dropclient (void)
2853 client_t *oldhostclient;
2854 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2855 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2856 if (clientnum < 0 || clientnum >= svs.maxclients)
2858 VM_Warning("dropclient: not a client\n");
2861 if (!svs.clients[clientnum].active)
2863 VM_Warning("dropclient: that client slot is not connected\n");
2866 oldhostclient = host_client;
2867 host_client = svs.clients + clientnum;
2868 SV_DropClient(false);
2869 host_client = oldhostclient;
2872 //entity() spawnclient (DP_SV_BOTCLIENT)
2873 static void VM_SV_spawnclient (void)
2877 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2878 prog->xfunction->builtinsprofile += 2;
2880 for (i = 0;i < svs.maxclients;i++)
2882 if (!svs.clients[i].active)
2884 prog->xfunction->builtinsprofile += 100;
2885 SV_ConnectClient (i, NULL);
2886 // this has to be set or else ClientDisconnect won't be called
2887 // we assume the qc will call ClientConnect...
2888 svs.clients[i].clientconnectcalled = true;
2889 ed = PRVM_EDICT_NUM(i + 1);
2893 VM_RETURN_EDICT(ed);
2896 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2897 static void VM_SV_clienttype (void)
2900 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2901 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2902 if (clientnum < 0 || clientnum >= svs.maxclients)
2903 PRVM_G_FLOAT(OFS_RETURN) = 3;
2904 else if (!svs.clients[clientnum].active)
2905 PRVM_G_FLOAT(OFS_RETURN) = 0;
2906 else if (svs.clients[clientnum].netconnection)
2907 PRVM_G_FLOAT(OFS_RETURN) = 1;
2909 PRVM_G_FLOAT(OFS_RETURN) = 2;
2916 string(string key) serverkey
2919 void VM_SV_serverkey(void)
2921 char string[VM_STRINGTEMP_LENGTH];
2922 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2923 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2924 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2927 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2928 static void VM_SV_setmodelindex (void)
2933 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2935 e = PRVM_G_EDICT(OFS_PARM0);
2936 if (e == prog->edicts)
2938 VM_Warning("setmodelindex: can not modify world entity\n");
2941 if (e->priv.server->free)
2943 VM_Warning("setmodelindex: can not modify free entity\n");
2946 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2947 if (i <= 0 || i >= MAX_MODELS)
2949 VM_Warning("setmodelindex: invalid modelindex\n");
2952 if (!sv.model_precache[i][0])
2954 VM_Warning("setmodelindex: model not precached\n");
2958 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2959 e->fields.server->modelindex = i;
2965 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2966 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2968 SetMinMaxSize (e, quakemins, quakemaxs, true);
2971 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2974 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2975 static void VM_SV_modelnameforindex (void)
2978 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2980 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2982 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2983 if (i <= 0 || i >= MAX_MODELS)
2985 VM_Warning("modelnameforindex: invalid modelindex\n");
2988 if (!sv.model_precache[i][0])
2990 VM_Warning("modelnameforindex: model not precached\n");
2994 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2997 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2998 static void VM_SV_particleeffectnum (void)
3001 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
3002 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
3005 PRVM_G_FLOAT(OFS_RETURN) = i;
3008 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3009 static void VM_SV_trailparticles (void)
3011 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
3013 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3016 MSG_WriteByte(&sv.datagram, svc_trailparticles);
3017 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
3018 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
3019 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
3020 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
3021 SV_FlushBroadcastMessages();
3024 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
3025 static void VM_SV_pointparticles (void)
3027 int effectnum, count;
3029 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
3031 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3034 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
3035 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
3036 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
3037 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
3038 if (count == 1 && !VectorLength2(vel))
3041 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
3042 MSG_WriteShort(&sv.datagram, effectnum);
3043 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3047 // 1+2+12+12+2=29 bytes
3048 MSG_WriteByte(&sv.datagram, svc_pointparticles);
3049 MSG_WriteShort(&sv.datagram, effectnum);
3050 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3051 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
3052 MSG_WriteShort(&sv.datagram, count);
3055 SV_FlushBroadcastMessages();
3058 //PF_setpause, // void(float pause) setpause = #531;
3059 static void VM_SV_setpause(void) {
3061 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
3062 if (pauseValue != 0) { //pause the game
3064 sv.pausedstart = Sys_DoubleTime();
3065 } else { //disable pause, in case it was enabled
3066 if (sv.paused != 0) {
3071 // send notification to all clients
3072 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
3073 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
3076 prvm_builtin_t vm_sv_builtins[] = {
3077 NULL, // #0 NULL function (not callable) (QUAKE)
3078 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3079 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3080 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3081 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3082 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3083 VM_break, // #6 void() break (QUAKE)
3084 VM_random, // #7 float() random (QUAKE)
3085 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3086 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3087 VM_error, // #10 void(string e) error (QUAKE)
3088 VM_objerror, // #11 void(string e) objerror (QUAKE)
3089 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3090 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3091 VM_spawn, // #14 entity() spawn (QUAKE)
3092 VM_remove, // #15 void(entity e) remove (QUAKE)
3093 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3094 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3095 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3096 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3097 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3098 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3099 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3100 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3101 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3102 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3103 VM_ftos, // #26 string(float f) ftos (QUAKE)
3104 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3105 VM_coredump, // #28 void() coredump (QUAKE)
3106 VM_traceon, // #29 void() traceon (QUAKE)
3107 VM_traceoff, // #30 void() traceoff (QUAKE)
3108 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3109 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3110 NULL, // #33 (QUAKE)
3111 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3112 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3113 VM_rint, // #36 float(float v) rint (QUAKE)
3114 VM_floor, // #37 float(float v) floor (QUAKE)
3115 VM_ceil, // #38 float(float v) ceil (QUAKE)
3116 NULL, // #39 (QUAKE)
3117 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3118 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3119 NULL, // #42 (QUAKE)
3120 VM_fabs, // #43 float(float f) fabs (QUAKE)
3121 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3122 VM_cvar, // #45 float(string s) cvar (QUAKE)
3123 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3124 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3125 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3126 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3127 NULL, // #50 (QUAKE)
3128 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3129 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3130 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3131 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3132 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3133 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3134 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3135 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3136 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3137 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3138 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3139 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3140 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3141 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3142 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3143 NULL, // #66 (QUAKE)
3144 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3145 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3146 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3147 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3148 NULL, // #71 (QUAKE)
3149 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3150 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3151 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3152 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3153 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3154 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3155 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3156 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3157 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3158 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3159 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3160 NULL, // #83 (QUAKE)
3161 NULL, // #84 (QUAKE)
3162 NULL, // #85 (QUAKE)
3163 NULL, // #86 (QUAKE)
3164 NULL, // #87 (QUAKE)
3165 NULL, // #88 (QUAKE)
3166 NULL, // #89 (QUAKE)
3167 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3168 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3169 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3170 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3171 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3172 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3173 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3174 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3175 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3176 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3177 // FrikaC and Telejano range #100-#199
3188 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3189 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3190 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3191 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3192 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3193 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3194 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3195 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3196 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3197 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3278 // FTEQW range #200-#299
3297 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3300 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3301 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3302 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3303 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3304 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3305 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3306 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3307 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3308 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3309 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3311 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3319 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3379 // CSQC range #300-#399
3380 NULL, // #300 void() clearscene (EXT_CSQC)
3381 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3382 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3383 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3384 NULL, // #304 void() renderscene (EXT_CSQC)
3385 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3386 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3387 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3388 NULL, // #308 void() R_EndPolygon
3390 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3391 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3395 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3396 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3397 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3398 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3399 NULL, // #319 void(string name) freepic (EXT_CSQC)
3400 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3401 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3402 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3403 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3404 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3405 NULL, // #325 void(void) drawresetcliparea
3410 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3411 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3412 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3413 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3414 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3415 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3416 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3417 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3418 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3419 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3420 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3421 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3422 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3423 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3424 NULL, // #344 vector() getmousepos (EXT_CSQC)
3425 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3426 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3427 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3428 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3429 NULL, // #349 float() isdemo (EXT_CSQC)
3430 VM_isserver, // #350 float() isserver (EXT_CSQC)
3431 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3432 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3433 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3434 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3440 NULL, // #360 float() readbyte (EXT_CSQC)
3441 NULL, // #361 float() readchar (EXT_CSQC)
3442 NULL, // #362 float() readshort (EXT_CSQC)
3443 NULL, // #363 float() readlong (EXT_CSQC)
3444 NULL, // #364 float() readcoord (EXT_CSQC)
3445 NULL, // #365 float() readangle (EXT_CSQC)
3446 NULL, // #366 string() readstring (EXT_CSQC)
3447 NULL, // #367 float() readfloat (EXT_CSQC)
3480 // LordHavoc's range #400-#499
3481 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3482 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3483 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3484 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3485 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3486 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3487 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3488 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3489 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)
3490 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3491 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3492 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3493 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3494 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3495 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3496 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3497 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3498 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3499 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3500 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3501 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3502 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3503 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3504 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3505 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3506 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3507 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3508 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3509 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3510 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3511 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3512 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3513 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3514 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3515 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3516 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3517 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3518 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3519 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3520 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3521 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3522 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3523 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3524 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3525 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3526 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3527 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3528 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3529 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3530 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3531 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3532 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3533 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3534 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3535 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3536 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3537 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3538 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3540 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3541 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3542 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3543 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3544 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3545 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3546 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3547 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3548 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3549 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3550 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3552 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3553 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3554 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3555 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3556 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3557 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3558 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3559 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3560 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3561 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3562 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3563 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3564 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3565 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3566 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3567 VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3575 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3576 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3577 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3578 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3579 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3580 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3581 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3582 VM_SV_WritePicture, // #501
3584 VM_whichpack, // #503 string(string) whichpack = #503;
3591 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3592 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3593 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3594 VM_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET)
3595 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3596 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3597 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3598 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3599 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3600 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3610 VM_loadfromdata, // #529
3611 VM_loadfromfile, // #530
3612 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3686 VM_callfunction, // #605
3687 VM_writetofile, // #606
3688 VM_isfunction, // #607
3694 VM_parseentitydata, // #613
3705 VM_SV_getextresponse, // #624 string getextresponse(void)
3709 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3711 void VM_SV_Cmd_Init(void)
3716 void VM_SV_Cmd_Reset(void)
3718 World_End(&sv.world);
3719 if(prog->funcoffsets.SV_Shutdown)
3721 func_t s = prog->funcoffsets.SV_Shutdown;
3722 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3723 PRVM_ExecuteProgram(s,"SV_Shutdown() required");