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 "
127 "DP_SV_BOUNCEFACTOR "
128 "DP_SV_CLIENTCOLORS "
131 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
132 "DP_SV_DRAWONLYTOCLIENT "
135 "DP_SV_ENTITYCONTENTSTRANSITION "
136 "DP_SV_MODELFLAGS_AS_EFFECTS "
137 "DP_SV_MOVETYPESTEP_LANDEVENT "
139 "DP_SV_NODRAWTOCLIENT "
140 "DP_SV_ONENTITYNOSPAWNFUNCTION "
141 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
143 "DP_SV_PLAYERPHYSICS "
144 "DP_SV_POINTPARTICLES "
146 "DP_SV_PRECACHEANYTIME "
150 "DP_SV_ROTATINGBMODEL "
154 "DP_SV_SPAWNFUNC_PREFIX "
155 "DP_SV_WRITEPICTURE "
156 "DP_SV_WRITEUNTERMINATEDSTRING "
160 "DP_TE_EXPLOSIONRGB "
162 "DP_TE_PARTICLECUBE "
163 "DP_TE_PARTICLERAIN "
164 "DP_TE_PARTICLESNOW "
166 "DP_TE_QUADEFFECTS1 "
169 "DP_TE_STANDARDEFFECTBUILTINS "
170 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
172 "DP_LIGHTSTYLE_STATICVALUE "
177 "KRIMZON_SV_PARSECLIENTCOMMAND "
180 "NEXUIZ_PLAYERMODEL "
182 "PRYDON_CLIENTCURSOR "
183 "TENEBRAE_GFX_DLIGHTS "
186 "DP_CSQC_SPAWNPARTICLE "
187 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
188 "DP_CSQC_ENTITYNOCULL "
189 //"EXT_CSQC " // not ready yet
196 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.
198 setorigin (entity, origin)
201 static void VM_SV_setorigin (void)
206 VM_SAFEPARMCOUNT(2, VM_setorigin);
208 e = PRVM_G_EDICT(OFS_PARM0);
209 if (e == prog->edicts)
211 VM_Warning("setorigin: can not modify world entity\n");
214 if (e->priv.server->free)
216 VM_Warning("setorigin: can not modify free entity\n");
219 org = PRVM_G_VECTOR(OFS_PARM1);
220 VectorCopy (org, e->fields.server->origin);
224 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
225 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
229 for (i=0 ; i<3 ; i++)
231 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
233 // set derived values
234 VectorCopy (min, e->fields.server->mins);
235 VectorCopy (max, e->fields.server->maxs);
236 VectorSubtract (max, min, e->fields.server->size);
245 the size box is rotated by the current angle
246 LordHavoc: no it isn't...
248 setsize (entity, minvector, maxvector)
251 static void VM_SV_setsize (void)
256 VM_SAFEPARMCOUNT(3, VM_setsize);
258 e = PRVM_G_EDICT(OFS_PARM0);
259 if (e == prog->edicts)
261 VM_Warning("setsize: can not modify world entity\n");
264 if (e->priv.server->free)
266 VM_Warning("setsize: can not modify free entity\n");
269 min = PRVM_G_VECTOR(OFS_PARM1);
270 max = PRVM_G_VECTOR(OFS_PARM2);
271 SetMinMaxSize (e, min, max, false);
279 setmodel(entity, model)
282 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
283 static void VM_SV_setmodel (void)
289 VM_SAFEPARMCOUNT(2, VM_setmodel);
291 e = PRVM_G_EDICT(OFS_PARM0);
292 if (e == prog->edicts)
294 VM_Warning("setmodel: can not modify world entity\n");
297 if (e->priv.server->free)
299 VM_Warning("setmodel: can not modify free entity\n");
302 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
303 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
304 e->fields.server->modelindex = i;
310 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
311 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
313 SetMinMaxSize (e, quakemins, quakemaxs, true);
316 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
323 single print to a specific client
325 sprint(clientent, value)
328 static void VM_SV_sprint (void)
332 char string[VM_STRINGTEMP_LENGTH];
334 VM_VarString(1, string, sizeof(string));
336 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
338 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
339 // LordHavoc: div0 requested that sprintto world operate like print
346 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
348 VM_Warning("tried to centerprint to a non-client\n");
352 client = svs.clients + entnum-1;
353 if (!client->netconnection)
356 MSG_WriteChar(&client->netconnection->message,svc_print);
357 MSG_WriteString(&client->netconnection->message, string);
365 single print to a specific client
367 centerprint(clientent, value)
370 static void VM_SV_centerprint (void)
374 char string[VM_STRINGTEMP_LENGTH];
376 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
378 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
380 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
382 VM_Warning("tried to centerprint to a non-client\n");
386 client = svs.clients + entnum-1;
387 if (!client->netconnection)
390 VM_VarString(1, string, sizeof(string));
391 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
392 MSG_WriteString(&client->netconnection->message, string);
399 particle(origin, color, count)
402 static void VM_SV_particle (void)
408 VM_SAFEPARMCOUNT(4, VM_SV_particle);
410 org = PRVM_G_VECTOR(OFS_PARM0);
411 dir = PRVM_G_VECTOR(OFS_PARM1);
412 color = PRVM_G_FLOAT(OFS_PARM2);
413 count = PRVM_G_FLOAT(OFS_PARM3);
414 SV_StartParticle (org, dir, (int)color, (int)count);
424 static void VM_SV_ambientsound (void)
428 float vol, attenuation;
431 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
433 pos = PRVM_G_VECTOR (OFS_PARM0);
434 samp = PRVM_G_STRING(OFS_PARM1);
435 vol = PRVM_G_FLOAT(OFS_PARM2);
436 attenuation = PRVM_G_FLOAT(OFS_PARM3);
438 // check to see if samp was properly precached
439 soundnum = SV_SoundIndex(samp, 1);
447 // add an svc_spawnambient command to the level signon packet
450 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
452 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
454 MSG_WriteVector(&sv.signon, pos, sv.protocol);
456 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
457 MSG_WriteShort (&sv.signon, soundnum);
459 MSG_WriteByte (&sv.signon, soundnum);
461 MSG_WriteByte (&sv.signon, (int)(vol*255));
462 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
470 Each entity can have eight independant sound sources, like voice,
473 Channel 0 is an auto-allocate channel, the others override anything
474 already running on that entity/channel pair.
476 An attenuation of 0 will play full volume everywhere in the level.
477 Larger attenuations will drop off.
481 static void VM_SV_sound (void)
485 prvm_edict_t *entity;
489 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
491 entity = PRVM_G_EDICT(OFS_PARM0);
492 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
493 sample = PRVM_G_STRING(OFS_PARM2);
494 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
495 attenuation = PRVM_G_FLOAT(OFS_PARM4);
498 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
502 if (volume < 0 || volume > 255)
504 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
508 if (attenuation < 0 || attenuation > 4)
510 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
514 if (channel < 0 || channel > 7)
516 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
520 SV_StartSound (entity, channel, sample, volume, attenuation);
527 Follows the same logic as VM_SV_sound, except instead of
528 an entity, an origin for the sound is provided, and channel
529 is omitted (since no entity is being tracked).
533 static void VM_SV_pointsound(void)
540 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
542 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
543 sample = PRVM_G_STRING(OFS_PARM1);
544 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
545 attenuation = PRVM_G_FLOAT(OFS_PARM3);
547 if (volume < 0 || volume > 255)
549 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
553 if (attenuation < 0 || attenuation > 4)
555 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
559 SV_StartPointSound (org, sample, volume, attenuation);
566 Used for use tracing and shot targeting
567 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
568 if the tryents flag is set.
570 traceline (vector1, vector2, movetype, ignore)
573 static void VM_SV_traceline (void)
580 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
582 prog->xfunction->builtinsprofile += 30;
584 v1 = PRVM_G_VECTOR(OFS_PARM0);
585 v2 = PRVM_G_VECTOR(OFS_PARM1);
586 move = (int)PRVM_G_FLOAT(OFS_PARM2);
587 ent = PRVM_G_EDICT(OFS_PARM3);
589 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]))
590 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));
592 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
594 VM_SetTraceGlobals(&trace);
602 Used for use tracing and shot targeting
603 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
604 if the tryents flag is set.
606 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
609 // LordHavoc: added this for my own use, VERY useful, similar to traceline
610 static void VM_SV_tracebox (void)
612 float *v1, *v2, *m1, *m2;
617 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
619 prog->xfunction->builtinsprofile += 30;
621 v1 = PRVM_G_VECTOR(OFS_PARM0);
622 m1 = PRVM_G_VECTOR(OFS_PARM1);
623 m2 = PRVM_G_VECTOR(OFS_PARM2);
624 v2 = PRVM_G_VECTOR(OFS_PARM3);
625 move = (int)PRVM_G_FLOAT(OFS_PARM4);
626 ent = PRVM_G_EDICT(OFS_PARM5);
628 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]))
629 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));
631 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
633 VM_SetTraceGlobals(&trace);
636 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
641 vec3_t original_origin;
642 vec3_t original_velocity;
643 vec3_t original_angles;
644 vec3_t original_avelocity;
648 VectorCopy(tossent->fields.server->origin , original_origin );
649 VectorCopy(tossent->fields.server->velocity , original_velocity );
650 VectorCopy(tossent->fields.server->angles , original_angles );
651 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
653 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
654 if (val != NULL && val->_float != 0)
655 gravity = val->_float;
658 gravity *= sv_gravity.value * 0.025;
660 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
662 SV_CheckVelocity (tossent);
663 tossent->fields.server->velocity[2] -= gravity;
664 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
665 VectorScale (tossent->fields.server->velocity, 0.05, move);
666 VectorAdd (tossent->fields.server->origin, move, end);
667 trace = SV_TraceBox(tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
668 VectorCopy (trace.endpos, tossent->fields.server->origin);
669 tossent->fields.server->velocity[2] -= gravity;
671 if (trace.fraction < 1)
675 VectorCopy(original_origin , tossent->fields.server->origin );
676 VectorCopy(original_velocity , tossent->fields.server->velocity );
677 VectorCopy(original_angles , tossent->fields.server->angles );
678 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
683 static void VM_SV_tracetoss (void)
687 prvm_edict_t *ignore;
689 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
691 prog->xfunction->builtinsprofile += 600;
693 ent = PRVM_G_EDICT(OFS_PARM0);
694 if (ent == prog->edicts)
696 VM_Warning("tracetoss: can not use world entity\n");
699 ignore = PRVM_G_EDICT(OFS_PARM1);
701 trace = SV_Trace_Toss (ent, ignore);
703 VM_SetTraceGlobals(&trace);
706 //============================================================================
708 static int checkpvsbytes;
709 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
711 static int VM_SV_newcheckclient (int check)
717 // cycle to the next one
719 check = bound(1, check, svs.maxclients);
720 if (check == svs.maxclients)
728 prog->xfunction->builtinsprofile++;
730 if (i == svs.maxclients+1)
732 // look up the client's edict
733 ent = PRVM_EDICT_NUM(i);
734 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
735 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
737 // found a valid client (possibly the same one again)
741 // get the PVS for the entity
742 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
744 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
745 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
754 Returns a client (or object that has a client enemy) that would be a
757 If there is more than one valid option, they are cycled each frame
759 If (self.origin + self.viewofs) is not in the PVS of the current target,
760 it is not returned at all.
765 int c_invis, c_notvis;
766 static void VM_SV_checkclient (void)
768 prvm_edict_t *ent, *self;
771 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
773 // find a new check if on a new frame
774 if (sv.time - sv.lastchecktime >= 0.1)
776 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
777 sv.lastchecktime = sv.time;
780 // return check if it might be visible
781 ent = PRVM_EDICT_NUM(sv.lastcheck);
782 if (ent->priv.server->free || ent->fields.server->health <= 0)
784 VM_RETURN_EDICT(prog->edicts);
788 // if current entity can't possibly see the check entity, return 0
789 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
790 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
791 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
794 VM_RETURN_EDICT(prog->edicts);
798 // might be able to see it
800 VM_RETURN_EDICT(ent);
803 //============================================================================
809 Checks if an entity is in a point's PVS.
810 Should be fast but can be inexact.
812 float checkpvs(vector viewpos, entity viewee) = #240;
815 static void VM_SV_checkpvs (void)
818 prvm_edict_t *viewee;
822 static int fatpvsbytes;
823 static unsigned char fatpvs[MAX_MAP_LEAFS/8];
826 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
827 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
828 viewee = PRVM_G_EDICT(OFS_PARM1);
830 if(viewee->priv.server->free)
832 VM_Warning("checkpvs: can not check free entity\n");
833 PRVM_G_FLOAT(OFS_RETURN) = 4;
838 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
840 // no PVS support on this worldmodel... darn
841 PRVM_G_FLOAT(OFS_RETURN) = 3;
844 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
847 // viewpos isn't in any PVS... darn
848 PRVM_G_FLOAT(OFS_RETURN) = 2;
851 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
853 // using fat PVS like FTEQW does (slow)
854 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
856 // no PVS support on this worldmodel... darn
857 PRVM_G_FLOAT(OFS_RETURN) = 3;
860 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
863 // viewpos isn't in any PVS... darn
864 PRVM_G_FLOAT(OFS_RETURN) = 2;
867 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
876 Sends text over to the client's execution buffer
878 stuffcmd (clientent, value, ...)
881 static void VM_SV_stuffcmd (void)
885 char string[VM_STRINGTEMP_LENGTH];
887 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
889 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
890 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
892 VM_Warning("Can't stuffcmd to a non-client\n");
896 VM_VarString(1, string, sizeof(string));
899 host_client = svs.clients + entnum-1;
900 Host_ClientCommands ("%s", string);
908 Returns a chain of entities that have origins within a spherical area
910 findradius (origin, radius)
913 static void VM_SV_findradius (void)
915 prvm_edict_t *ent, *chain;
916 vec_t radius, radius2;
917 vec3_t org, eorg, mins, maxs;
920 prvm_edict_t *touchedicts[MAX_EDICTS];
923 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
926 chainfield = PRVM_G_INT(OFS_PARM2);
928 chainfield = prog->fieldoffsets.chain;
930 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
932 chain = (prvm_edict_t *)prog->edicts;
934 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
935 radius = PRVM_G_FLOAT(OFS_PARM1);
936 radius2 = radius * radius;
938 mins[0] = org[0] - (radius + 1);
939 mins[1] = org[1] - (radius + 1);
940 mins[2] = org[2] - (radius + 1);
941 maxs[0] = org[0] + (radius + 1);
942 maxs[1] = org[1] + (radius + 1);
943 maxs[2] = org[2] + (radius + 1);
944 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
945 if (numtouchedicts > MAX_EDICTS)
947 // this never happens
948 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
949 numtouchedicts = MAX_EDICTS;
951 for (i = 0;i < numtouchedicts;i++)
953 ent = touchedicts[i];
954 prog->xfunction->builtinsprofile++;
955 // Quake did not return non-solid entities but darkplaces does
956 // (note: this is the reason you can't blow up fallen zombies)
957 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
959 // LordHavoc: compare against bounding box rather than center so it
960 // doesn't miss large objects, and use DotProduct instead of Length
961 // for a major speedup
962 VectorSubtract(org, ent->fields.server->origin, eorg);
963 if (sv_gameplayfix_findradiusdistancetobox.integer)
965 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
966 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
967 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
970 VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
971 if (DotProduct(eorg, eorg) < radius2)
973 PRVM_EDICTFIELDVALUE(ent,chainfield)->edict = PRVM_EDICT_TO_PROG(chain);
978 VM_RETURN_EDICT(chain);
981 static void VM_SV_precache_sound (void)
983 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
984 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
987 static void VM_SV_precache_model (void)
989 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
990 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
991 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
998 float(float yaw, float dist[, settrace]) walkmove
1001 static void VM_SV_walkmove (void)
1010 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1012 // assume failure if it returns early
1013 PRVM_G_FLOAT(OFS_RETURN) = 0;
1015 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1016 if (ent == prog->edicts)
1018 VM_Warning("walkmove: can not modify world entity\n");
1021 if (ent->priv.server->free)
1023 VM_Warning("walkmove: can not modify free entity\n");
1026 yaw = PRVM_G_FLOAT(OFS_PARM0);
1027 dist = PRVM_G_FLOAT(OFS_PARM1);
1028 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1030 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1033 yaw = yaw*M_PI*2 / 360;
1035 move[0] = cos(yaw)*dist;
1036 move[1] = sin(yaw)*dist;
1039 // save program state, because SV_movestep may call other progs
1040 oldf = prog->xfunction;
1041 oldself = prog->globals.server->self;
1043 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1046 // restore program state
1047 prog->xfunction = oldf;
1048 prog->globals.server->self = oldself;
1058 static void VM_SV_droptofloor (void)
1064 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1066 // assume failure if it returns early
1067 PRVM_G_FLOAT(OFS_RETURN) = 0;
1069 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1070 if (ent == prog->edicts)
1072 VM_Warning("droptofloor: can not modify world entity\n");
1075 if (ent->priv.server->free)
1077 VM_Warning("droptofloor: can not modify free entity\n");
1081 VectorCopy (ent->fields.server->origin, end);
1084 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1085 SV_UnstickEntity(ent);
1087 trace = SV_TraceBox(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1088 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1091 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]);
1092 VectorAdd(ent->fields.server->origin, offset, org);
1093 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1094 VectorSubtract(trace.endpos, offset, trace.endpos);
1095 if (trace.startsolid)
1097 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]);
1098 SV_UnstickEntity(ent);
1100 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1101 ent->fields.server->groundentity = 0;
1102 PRVM_G_FLOAT(OFS_RETURN) = 1;
1104 else if (trace.fraction < 1)
1106 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]);
1107 VectorCopy (trace.endpos, ent->fields.server->origin);
1108 SV_UnstickEntity(ent);
1110 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1111 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1112 PRVM_G_FLOAT(OFS_RETURN) = 1;
1113 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1114 ent->priv.server->suspendedinairflag = true;
1119 if (trace.fraction != 1)
1121 if (trace.fraction < 1)
1122 VectorCopy (trace.endpos, ent->fields.server->origin);
1124 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1125 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1126 PRVM_G_FLOAT(OFS_RETURN) = 1;
1127 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1128 ent->priv.server->suspendedinairflag = true;
1137 void(float style, string value) lightstyle
1140 static void VM_SV_lightstyle (void)
1147 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1149 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1150 val = PRVM_G_STRING(OFS_PARM1);
1152 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1153 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1156 // change the string in sv
1157 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1159 // send message to all clients on this server
1160 if (sv.state != ss_active)
1163 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1165 if (client->active && client->netconnection)
1167 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1168 MSG_WriteChar (&client->netconnection->message,style);
1169 MSG_WriteString (&client->netconnection->message, val);
1179 static void VM_SV_checkbottom (void)
1181 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1182 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1190 static void VM_SV_pointcontents (void)
1192 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1193 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1200 Pick a vector for the player to shoot along
1201 vector aim(entity, missilespeed)
1204 static void VM_SV_aim (void)
1206 prvm_edict_t *ent, *check, *bestent;
1207 vec3_t start, dir, end, bestdir;
1210 float dist, bestdist;
1213 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1215 // assume failure if it returns early
1216 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1217 // if sv_aim is so high it can't possibly accept anything, skip out early
1218 if (sv_aim.value >= 1)
1221 ent = PRVM_G_EDICT(OFS_PARM0);
1222 if (ent == prog->edicts)
1224 VM_Warning("aim: can not use world entity\n");
1227 if (ent->priv.server->free)
1229 VM_Warning("aim: can not use free entity\n");
1232 speed = PRVM_G_FLOAT(OFS_PARM1);
1234 VectorCopy (ent->fields.server->origin, start);
1237 // try sending a trace straight
1238 VectorCopy (prog->globals.server->v_forward, dir);
1239 VectorMA (start, 2048, dir, end);
1240 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1241 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1242 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1244 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1249 // try all possible entities
1250 VectorCopy (dir, bestdir);
1251 bestdist = sv_aim.value;
1254 check = PRVM_NEXT_EDICT(prog->edicts);
1255 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1257 prog->xfunction->builtinsprofile++;
1258 if (check->fields.server->takedamage != DAMAGE_AIM)
1262 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1263 continue; // don't aim at teammate
1264 for (j=0 ; j<3 ; j++)
1265 end[j] = check->fields.server->origin[j]
1266 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1267 VectorSubtract (end, start, dir);
1268 VectorNormalize (dir);
1269 dist = DotProduct (dir, prog->globals.server->v_forward);
1270 if (dist < bestdist)
1271 continue; // to far to turn
1272 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1273 if (tr.ent == check)
1274 { // can shoot at this one
1282 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1283 dist = DotProduct (dir, prog->globals.server->v_forward);
1284 VectorScale (prog->globals.server->v_forward, dist, end);
1286 VectorNormalize (end);
1287 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1291 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1296 ===============================================================================
1300 ===============================================================================
1303 #define MSG_BROADCAST 0 // unreliable to all
1304 #define MSG_ONE 1 // reliable to one (msg_entity)
1305 #define MSG_ALL 2 // reliable to all
1306 #define MSG_INIT 3 // write to the init string
1307 #define MSG_ENTITY 5
1309 sizebuf_t *WriteDest (void)
1315 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1319 return &sv.datagram;
1322 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1323 entnum = PRVM_NUM_FOR_EDICT(ent);
1324 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1326 VM_Warning ("WriteDest: tried to write to non-client\n");
1327 return &sv.reliable_datagram;
1330 return &svs.clients[entnum-1].netconnection->message;
1333 VM_Warning ("WriteDest: bad destination\n");
1335 return &sv.reliable_datagram;
1341 return sv.writeentitiestoclient_msg;
1347 static void VM_SV_WriteByte (void)
1349 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1350 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1353 static void VM_SV_WriteChar (void)
1355 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1356 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1359 static void VM_SV_WriteShort (void)
1361 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1362 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1365 static void VM_SV_WriteLong (void)
1367 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1368 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1371 static void VM_SV_WriteAngle (void)
1373 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1374 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1377 static void VM_SV_WriteCoord (void)
1379 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1380 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1383 static void VM_SV_WriteString (void)
1385 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1386 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1389 static void VM_SV_WriteUnterminatedString (void)
1391 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1392 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1396 static void VM_SV_WriteEntity (void)
1398 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1399 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1402 // writes a picture as at most size bytes of data
1404 // IMGNAME \0 SIZE(short) IMGDATA
1405 // if failed to read/compress:
1407 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1408 static void VM_SV_WritePicture (void)
1410 const char *imgname;
1414 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1416 imgname = PRVM_G_STRING(OFS_PARM1);
1417 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1421 MSG_WriteString(WriteDest(), imgname);
1422 if(Image_Compress(imgname, size, &buf, &size))
1425 MSG_WriteShort(WriteDest(), size);
1426 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1431 MSG_WriteShort(WriteDest(), 0);
1435 //////////////////////////////////////////////////////////
1437 static void VM_SV_makestatic (void)
1442 // allow 0 parameters due to an id1 qc bug in which this function is used
1443 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1444 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1446 if (prog->argc >= 1)
1447 ent = PRVM_G_EDICT(OFS_PARM0);
1449 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1450 if (ent == prog->edicts)
1452 VM_Warning("makestatic: can not modify world entity\n");
1455 if (ent->priv.server->free)
1457 VM_Warning("makestatic: can not modify free entity\n");
1462 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1467 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1468 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1469 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1471 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1473 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1474 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1475 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1479 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1480 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1481 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1484 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1485 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1486 for (i=0 ; i<3 ; i++)
1488 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1489 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1492 // throw the entity away now
1496 //=============================================================================
1503 static void VM_SV_setspawnparms (void)
1509 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1511 ent = PRVM_G_EDICT(OFS_PARM0);
1512 i = PRVM_NUM_FOR_EDICT(ent);
1513 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1515 Con_Print("tried to setspawnparms on a non-client\n");
1519 // copy spawn parms out of the client_t
1520 client = svs.clients + i-1;
1521 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1522 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1529 Returns a color vector indicating the lighting at the requested point.
1531 (Internal Operation note: actually measures the light beneath the point, just like
1532 the model lighting on the client)
1537 static void VM_SV_getlight (void)
1539 vec3_t ambientcolor, diffusecolor, diffusenormal;
1541 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1542 p = PRVM_G_VECTOR(OFS_PARM0);
1543 VectorClear(ambientcolor);
1544 VectorClear(diffusecolor);
1545 VectorClear(diffusenormal);
1546 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1547 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1548 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1553 unsigned char type; // 1/2/8 or other value if isn't used
1557 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1558 static int vm_customstats_last;
1560 void VM_CustomStats_Clear (void)
1564 Z_Free(vm_customstats);
1565 vm_customstats = NULL;
1566 vm_customstats_last = -1;
1570 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1578 for(i=0; i<vm_customstats_last+1 ;i++)
1580 if(!vm_customstats[i].type)
1582 switch(vm_customstats[i].type)
1584 //string as 16 bytes
1587 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1588 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1589 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1590 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1591 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1593 //float field sent as-is
1595 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1597 //integer value of float field
1599 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1607 // void(float index, float type, .void field) SV_AddStat = #232;
1608 // Set up an auto-sent player stat.
1609 // Client's get thier own fields sent to them. Index may not be less than 32.
1610 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1611 // 1: string (4 stats carrying a total of 16 charactures)
1612 // 2: float (one stat, float converted to an integer for transportation)
1613 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1614 static void VM_SV_AddStat (void)
1619 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1623 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1626 VM_Warning("PF_SV_AddStat: not enough memory\n");
1630 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1631 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1632 off = PRVM_G_INT (OFS_PARM2);
1637 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1640 if(i >= (MAX_CL_STATS-32))
1642 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1645 if(i > (MAX_CL_STATS-32-4) && type == 1)
1647 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1650 vm_customstats[i].type = type;
1651 vm_customstats[i].fieldoffset = off;
1652 if(vm_customstats_last < i)
1653 vm_customstats_last = i;
1660 copies data from one entity to another
1662 copyentity(src, dst)
1665 static void VM_SV_copyentity (void)
1667 prvm_edict_t *in, *out;
1668 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1669 in = PRVM_G_EDICT(OFS_PARM0);
1670 if (in == prog->edicts)
1672 VM_Warning("copyentity: can not read world entity\n");
1675 if (in->priv.server->free)
1677 VM_Warning("copyentity: can not read free entity\n");
1680 out = PRVM_G_EDICT(OFS_PARM1);
1681 if (out == prog->edicts)
1683 VM_Warning("copyentity: can not modify world entity\n");
1686 if (out->priv.server->free)
1688 VM_Warning("copyentity: can not modify free entity\n");
1691 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1700 sets the color of a client and broadcasts the update to all connected clients
1702 setcolor(clientent, value)
1705 static void VM_SV_setcolor (void)
1711 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1712 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1713 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1715 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1717 Con_Print("tried to setcolor a non-client\n");
1721 client = svs.clients + entnum-1;
1724 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1726 client->edict->fields.server->team = (i & 15) + 1;
1729 if (client->old_colors != client->colors)
1731 client->old_colors = client->colors;
1732 // send notification to all clients
1733 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1734 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1735 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1743 effect(origin, modelname, startframe, framecount, framerate)
1746 static void VM_SV_effect (void)
1750 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1751 s = PRVM_G_STRING(OFS_PARM1);
1754 VM_Warning("effect: no model specified\n");
1758 i = SV_ModelIndex(s, 1);
1761 VM_Warning("effect: model not precached\n");
1765 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1767 VM_Warning("effect: framecount < 1\n");
1771 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1773 VM_Warning("effect: framerate < 1\n");
1777 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));
1780 static void VM_SV_te_blood (void)
1782 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1783 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1785 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1786 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1788 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1789 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1790 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1792 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1793 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1794 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1796 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1797 SV_FlushBroadcastMessages();
1800 static void VM_SV_te_bloodshower (void)
1802 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1803 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1805 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1806 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1808 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1809 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1810 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1812 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1813 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1814 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1816 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1818 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1819 SV_FlushBroadcastMessages();
1822 static void VM_SV_te_explosionrgb (void)
1824 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1825 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1826 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1828 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1830 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1832 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1833 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1834 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1835 SV_FlushBroadcastMessages();
1838 static void VM_SV_te_particlecube (void)
1840 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1841 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1843 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1844 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1847 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1848 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1850 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1851 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1852 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1854 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1855 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1856 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1858 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1860 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1861 // gravity true/false
1862 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1864 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1865 SV_FlushBroadcastMessages();
1868 static void VM_SV_te_particlerain (void)
1870 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1871 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1873 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1874 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1876 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1877 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1878 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1880 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1881 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1882 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1884 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1885 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1886 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1888 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1890 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1891 SV_FlushBroadcastMessages();
1894 static void VM_SV_te_particlesnow (void)
1896 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1897 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1899 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1900 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1911 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1912 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1914 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1916 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1917 SV_FlushBroadcastMessages();
1920 static void VM_SV_te_spark (void)
1922 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1923 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1925 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1926 MSG_WriteByte(&sv.datagram, TE_SPARK);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1932 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1933 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1934 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1936 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1937 SV_FlushBroadcastMessages();
1940 static void VM_SV_te_gunshotquad (void)
1942 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1943 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1944 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1948 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1949 SV_FlushBroadcastMessages();
1952 static void VM_SV_te_spikequad (void)
1954 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1955 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1956 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1961 SV_FlushBroadcastMessages();
1964 static void VM_SV_te_superspikequad (void)
1966 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1967 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1968 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1970 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1972 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1973 SV_FlushBroadcastMessages();
1976 static void VM_SV_te_explosionquad (void)
1978 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
1979 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1980 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1983 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1984 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1985 SV_FlushBroadcastMessages();
1988 static void VM_SV_te_smallflash (void)
1990 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
1991 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1992 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1994 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1995 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1996 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1997 SV_FlushBroadcastMessages();
2000 static void VM_SV_te_customflash (void)
2002 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2003 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2005 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2006 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2008 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2009 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2010 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2012 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2014 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2016 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2017 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2018 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2019 SV_FlushBroadcastMessages();
2022 static void VM_SV_te_gunshot (void)
2024 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2025 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2026 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2028 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2029 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2030 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2031 SV_FlushBroadcastMessages();
2034 static void VM_SV_te_spike (void)
2036 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2037 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2038 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2040 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2041 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2042 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2043 SV_FlushBroadcastMessages();
2046 static void VM_SV_te_superspike (void)
2048 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2049 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2050 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2052 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2054 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2055 SV_FlushBroadcastMessages();
2058 static void VM_SV_te_explosion (void)
2060 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2061 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2062 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2064 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2065 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2066 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2067 SV_FlushBroadcastMessages();
2070 static void VM_SV_te_tarexplosion (void)
2072 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2073 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2074 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2076 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2077 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2078 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2079 SV_FlushBroadcastMessages();
2082 static void VM_SV_te_wizspike (void)
2084 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2085 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2086 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2088 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2089 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2090 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2091 SV_FlushBroadcastMessages();
2094 static void VM_SV_te_knightspike (void)
2096 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2097 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2098 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2100 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2101 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2102 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2103 SV_FlushBroadcastMessages();
2106 static void VM_SV_te_lavasplash (void)
2108 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2109 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2110 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2112 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2113 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2114 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2115 SV_FlushBroadcastMessages();
2118 static void VM_SV_te_teleport (void)
2120 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2121 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2122 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2124 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2125 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2126 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2127 SV_FlushBroadcastMessages();
2130 static void VM_SV_te_explosion2 (void)
2132 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2133 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2134 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2136 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2137 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2138 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2140 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2141 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2142 SV_FlushBroadcastMessages();
2145 static void VM_SV_te_lightning1 (void)
2147 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2148 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2149 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2151 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2153 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2154 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2155 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2157 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2158 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2159 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2160 SV_FlushBroadcastMessages();
2163 static void VM_SV_te_lightning2 (void)
2165 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2166 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2167 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2169 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2171 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2172 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2173 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2175 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2176 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2177 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2178 SV_FlushBroadcastMessages();
2181 static void VM_SV_te_lightning3 (void)
2183 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2184 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2185 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2187 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2189 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2190 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2191 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2193 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2194 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2195 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2196 SV_FlushBroadcastMessages();
2199 static void VM_SV_te_beam (void)
2201 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2202 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2203 MSG_WriteByte(&sv.datagram, TE_BEAM);
2205 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2207 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2208 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2209 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2211 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2212 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2213 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2214 SV_FlushBroadcastMessages();
2217 static void VM_SV_te_plasmaburn (void)
2219 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2220 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2221 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2222 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2223 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2224 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2225 SV_FlushBroadcastMessages();
2228 static void VM_SV_te_flamejet (void)
2230 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2231 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2232 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2234 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2235 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2236 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2238 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2239 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2240 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2242 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2243 SV_FlushBroadcastMessages();
2246 void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2249 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2251 bestdist = 1000000000;
2253 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2255 // clip original point to each triangle of the surface and find the
2256 // triangle that is closest
2257 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2258 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2259 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2260 TriangleNormal(v[0], v[1], v[2], facenormal);
2261 VectorNormalize(facenormal);
2262 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2263 VectorMA(p, offsetdist, facenormal, temp);
2264 for (j = 0, k = 2;j < 3;k = j, j++)
2266 VectorSubtract(v[k], v[j], edgenormal);
2267 CrossProduct(edgenormal, facenormal, sidenormal);
2268 VectorNormalize(sidenormal);
2269 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2271 VectorMA(temp, offsetdist, sidenormal, temp);
2273 dist = VectorDistance2(temp, p);
2274 if (bestdist > dist)
2277 VectorCopy(temp, out);
2282 static dp_model_t *getmodel(prvm_edict_t *ed)
2285 if (!ed || ed->priv.server->free)
2287 modelindex = (int)ed->fields.server->modelindex;
2288 if (modelindex < 1 || modelindex >= MAX_MODELS)
2290 return sv.models[modelindex];
2293 static msurface_t *getsurface(dp_model_t *model, int surfacenum)
2295 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2297 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2301 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2302 static void VM_SV_getsurfacenumpoints(void)
2305 msurface_t *surface;
2306 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints);
2307 // return 0 if no such surface
2308 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2310 PRVM_G_FLOAT(OFS_RETURN) = 0;
2314 // note: this (incorrectly) assumes it is a simple polygon
2315 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2317 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2318 static void VM_SV_getsurfacepoint(void)
2322 msurface_t *surface;
2324 VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint);
2325 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2326 ed = PRVM_G_EDICT(OFS_PARM0);
2327 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2329 // note: this (incorrectly) assumes it is a simple polygon
2330 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2331 if (pointnum < 0 || pointnum >= surface->num_vertices)
2333 // FIXME: implement rotation/scaling
2334 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2336 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
2337 // float SPA_POSITION = 0;
2338 // float SPA_S_AXIS = 1;
2339 // float SPA_T_AXIS = 2;
2340 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2341 // float SPA_TEXCOORDS0 = 4;
2342 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2343 // float SPA_LIGHTMAP0_COLOR = 6;
2344 static void VM_SV_getsurfacepointattribute(void)
2348 msurface_t *surface;
2352 VM_SAFEPARMCOUNT(4, VM_SV_getsurfacepoint);
2353 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2354 ed = PRVM_G_EDICT(OFS_PARM0);
2355 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2357 // note: this (incorrectly) assumes it is a simple polygon
2358 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2359 if (pointnum < 0 || pointnum >= surface->num_vertices)
2361 // FIXME: implement rotation/scaling
2362 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
2364 switch( attributetype ) {
2365 // float SPA_POSITION = 0;
2367 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2369 // float SPA_S_AXIS = 1;
2371 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2373 // float SPA_T_AXIS = 2;
2375 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2377 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2379 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2381 // float SPA_TEXCOORDS0 = 4;
2383 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2384 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
2385 ret[0] = texcoord[0];
2386 ret[1] = texcoord[1];
2390 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2392 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2393 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
2394 ret[0] = texcoord[0];
2395 ret[1] = texcoord[1];
2399 // float SPA_LIGHTMAP0_COLOR = 6;
2401 // ignore alpha for now..
2402 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2405 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2409 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2410 static void VM_SV_getsurfacenormal(void)
2413 msurface_t *surface;
2415 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal);
2416 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2417 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2419 // FIXME: implement rotation/scaling
2420 // note: this (incorrectly) assumes it is a simple polygon
2421 // note: this only returns the first triangle, so it doesn't work very
2422 // well for curved surfaces or arbitrary meshes
2423 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);
2424 VectorNormalize(normal);
2425 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2427 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2428 static void VM_SV_getsurfacetexture(void)
2431 msurface_t *surface;
2432 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture);
2433 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2434 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2436 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2438 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2439 static void VM_SV_getsurfacenearpoint(void)
2441 int surfacenum, best;
2443 vec_t dist, bestdist;
2446 msurface_t *surface;
2448 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint);
2449 PRVM_G_FLOAT(OFS_RETURN) = -1;
2450 ed = PRVM_G_EDICT(OFS_PARM0);
2451 point = PRVM_G_VECTOR(OFS_PARM1);
2453 if (!ed || ed->priv.server->free)
2455 model = getmodel(ed);
2456 if (!model || !model->num_surfaces)
2459 // FIXME: implement rotation/scaling
2460 VectorSubtract(point, ed->fields.server->origin, p);
2462 bestdist = 1000000000;
2463 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2465 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2466 // first see if the nearest point on the surface's box is closer than the previous match
2467 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2468 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2469 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2470 dist = VectorLength2(clipped);
2471 if (dist < bestdist)
2473 // it is, check the nearest point on the actual geometry
2474 clippointtosurface(model, surface, p, clipped);
2475 VectorSubtract(clipped, p, clipped);
2476 dist += VectorLength2(clipped);
2477 if (dist < bestdist)
2479 // that's closer too, store it as the best match
2485 PRVM_G_FLOAT(OFS_RETURN) = best;
2487 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2488 static void VM_SV_getsurfaceclippedpoint(void)
2492 msurface_t *surface;
2494 VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint);
2495 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2496 ed = PRVM_G_EDICT(OFS_PARM0);
2497 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2499 // FIXME: implement rotation/scaling
2500 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2501 clippointtosurface(model, surface, p, out);
2502 // FIXME: implement rotation/scaling
2503 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2506 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2507 //this function originally written by KrimZon, made shorter by LordHavoc
2508 static void VM_SV_clientcommand (void)
2510 client_t *temp_client;
2512 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2514 //find client for this entity
2515 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2516 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2518 Con_Print("PF_clientcommand: entity is not a client\n");
2522 temp_client = host_client;
2523 host_client = svs.clients + i;
2524 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2525 host_client = temp_client;
2528 //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)
2529 static void VM_SV_setattachment (void)
2531 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2532 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2533 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2537 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2539 if (e == prog->edicts)
2541 VM_Warning("setattachment: can not modify world entity\n");
2544 if (e->priv.server->free)
2546 VM_Warning("setattachment: can not modify free entity\n");
2550 if (tagentity == NULL)
2551 tagentity = prog->edicts;
2553 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2555 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2557 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2560 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2562 modelindex = (int)tagentity->fields.server->modelindex;
2563 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2565 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2567 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);
2570 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));
2574 /////////////////////////////////////////
2575 // DP_MD3_TAGINFO extension coded by VorteX
2577 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2582 i = (int)e->fields.server->modelindex;
2583 if (i < 1 || i >= MAX_MODELS)
2585 model = sv.models[i];
2587 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2590 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2599 Matrix4x4_CreateIdentity(tag_localmatrix);
2602 && (modelindex = (int)e->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2603 && (model = sv.models[(int)e->fields.server->modelindex])
2604 && model->animscenes)
2606 frame = (int)e->fields.server->frame;
2607 if (frame < 0 || frame >= model->numframes)
2610 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)e->fields.server->skin, model->animscenes[frame].firstframe, tagindex - 1, parentindex, tagname, tag_localmatrix);
2621 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2625 float pitchsign = 1;
2628 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2629 if (val && val->_float != 0)
2630 scale = val->_float;
2633 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);
2636 pitchsign = SV_GetPitchSign(ent);
2637 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);
2641 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2647 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2648 && (model = sv.models[(int)ent->fields.server->modelindex])
2649 && model->animscenes)
2651 // if model has wrong frame, engine automatically switches to model first frame
2652 frame = (int)ent->fields.server->frame;
2653 if (frame < 0 || frame >= model->numframes)
2655 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2657 *out = identitymatrix;
2661 // Warnings/errors code:
2662 // 0 - normal (everything all-right)
2665 // 3 - null or non-precached model
2666 // 4 - no tags with requested index
2667 // 5 - runaway loop at attachment chain
2668 extern cvar_t cl_bob;
2669 extern cvar_t cl_bobcycle;
2670 extern cvar_t cl_bobup;
2671 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2675 int modelindex, attachloop;
2676 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2679 *out = identitymatrix; // warnings and errors return identical matrix
2681 if (ent == prog->edicts)
2683 if (ent->priv.server->free)
2686 modelindex = (int)ent->fields.server->modelindex;
2687 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2690 model = sv.models[modelindex];
2692 tagmatrix = identitymatrix;
2693 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2697 if (attachloop >= 256) // prevent runaway looping
2699 // apply transformation by child's tagindex on parent entity and then
2700 // by parent entity itself
2701 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2702 if (ret && attachloop == 0)
2704 SV_GetEntityMatrix(ent, &entitymatrix, false);
2705 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2706 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2707 // next iteration we process the parent entity
2708 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2710 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2711 ent = PRVM_EDICT_NUM(val->edict);
2718 // RENDER_VIEWMODEL magic
2719 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2721 Matrix4x4_Copy(&tagmatrix, out);
2722 ent = PRVM_EDICT_NUM(val->edict);
2724 SV_GetEntityMatrix(ent, &entitymatrix, true);
2725 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2728 // Cl_bob, ported from rendering code
2729 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2732 // LordHavoc: this code is *weird*, but not replacable (I think it
2733 // should be done in QC on the server, but oh well, quake is quake)
2734 // LordHavoc: figured out bobup: the time at which the sin is at 180
2735 // degrees (which allows lengthening or squishing the peak or valley)
2736 cycle = sv.time/cl_bobcycle.value;
2737 cycle -= (int)cycle;
2738 if (cycle < cl_bobup.value)
2739 cycle = sin(M_PI * cycle / cl_bobup.value);
2741 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2742 // bob is proportional to velocity in the xy plane
2743 // (don't count Z, or jumping messes it up)
2744 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;
2745 bob = bob*0.3 + bob*0.7*cycle;
2746 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2753 //float(entity ent, string tagname) gettagindex;
2755 static void VM_SV_gettagindex (void)
2758 const char *tag_name;
2759 int modelindex, tag_index;
2761 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2763 ent = PRVM_G_EDICT(OFS_PARM0);
2764 tag_name = PRVM_G_STRING(OFS_PARM1);
2766 if (ent == prog->edicts)
2768 VM_Warning("gettagindex: can't affect world entity\n");
2771 if (ent->priv.server->free)
2773 VM_Warning("gettagindex: can't affect free entity\n");
2777 modelindex = (int)ent->fields.server->modelindex;
2779 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2780 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2783 tag_index = SV_GetTagIndex(ent, tag_name);
2785 if(developer.integer >= 100)
2786 Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2788 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2791 //vector(entity ent, float tagindex) gettaginfo;
2792 static void VM_SV_gettaginfo (void)
2796 matrix4x4_t tag_matrix;
2797 matrix4x4_t tag_localmatrix;
2799 const char *tagname;
2802 vec3_t fo, le, up, trans;
2804 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2806 e = PRVM_G_EDICT(OFS_PARM0);
2807 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2809 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2810 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, le, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2811 VectorScale(le, -1, prog->globals.server->v_right);
2812 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2813 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2815 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_parent)))
2816 val->_float = parentindex;
2817 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_name)))
2818 val->string = tagname ? PRVM_SetTempString(tagname) : 0;
2819 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_offset)))
2820 VectorCopy(trans, val->vector);
2821 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_forward)))
2822 VectorCopy(fo, val->vector);
2823 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_right)))
2824 VectorScale(le, -1, val->vector);
2825 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_up)))
2826 VectorCopy(up, val->vector);
2831 VM_Warning("gettagindex: can't affect world entity\n");
2834 VM_Warning("gettagindex: can't affect free entity\n");
2837 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2840 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2843 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2848 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2849 static void VM_SV_dropclient (void)
2852 client_t *oldhostclient;
2853 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2854 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2855 if (clientnum < 0 || clientnum >= svs.maxclients)
2857 VM_Warning("dropclient: not a client\n");
2860 if (!svs.clients[clientnum].active)
2862 VM_Warning("dropclient: that client slot is not connected\n");
2865 oldhostclient = host_client;
2866 host_client = svs.clients + clientnum;
2867 SV_DropClient(false);
2868 host_client = oldhostclient;
2871 //entity() spawnclient (DP_SV_BOTCLIENT)
2872 static void VM_SV_spawnclient (void)
2876 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2877 prog->xfunction->builtinsprofile += 2;
2879 for (i = 0;i < svs.maxclients;i++)
2881 if (!svs.clients[i].active)
2883 prog->xfunction->builtinsprofile += 100;
2884 SV_ConnectClient (i, NULL);
2885 // this has to be set or else ClientDisconnect won't be called
2886 // we assume the qc will call ClientConnect...
2887 svs.clients[i].clientconnectcalled = true;
2888 ed = PRVM_EDICT_NUM(i + 1);
2892 VM_RETURN_EDICT(ed);
2895 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2896 static void VM_SV_clienttype (void)
2899 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2900 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2901 if (clientnum < 0 || clientnum >= svs.maxclients)
2902 PRVM_G_FLOAT(OFS_RETURN) = 3;
2903 else if (!svs.clients[clientnum].active)
2904 PRVM_G_FLOAT(OFS_RETURN) = 0;
2905 else if (svs.clients[clientnum].netconnection)
2906 PRVM_G_FLOAT(OFS_RETURN) = 1;
2908 PRVM_G_FLOAT(OFS_RETURN) = 2;
2915 string(string key) serverkey
2918 void VM_SV_serverkey(void)
2920 char string[VM_STRINGTEMP_LENGTH];
2921 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2922 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2923 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2926 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2927 static void VM_SV_setmodelindex (void)
2932 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2934 e = PRVM_G_EDICT(OFS_PARM0);
2935 if (e == prog->edicts)
2937 VM_Warning("setmodelindex: can not modify world entity\n");
2940 if (e->priv.server->free)
2942 VM_Warning("setmodelindex: can not modify free entity\n");
2945 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2946 if (i <= 0 || i >= MAX_MODELS)
2948 VM_Warning("setmodelindex: invalid modelindex\n");
2951 if (!sv.model_precache[i][0])
2953 VM_Warning("setmodelindex: model not precached\n");
2957 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2958 e->fields.server->modelindex = i;
2964 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2965 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2967 SetMinMaxSize (e, quakemins, quakemaxs, true);
2970 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2973 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2974 static void VM_SV_modelnameforindex (void)
2977 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2979 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2981 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2982 if (i <= 0 || i >= MAX_MODELS)
2984 VM_Warning("modelnameforindex: invalid modelindex\n");
2987 if (!sv.model_precache[i][0])
2989 VM_Warning("modelnameforindex: model not precached\n");
2993 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2996 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2997 static void VM_SV_particleeffectnum (void)
3000 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
3001 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
3004 PRVM_G_FLOAT(OFS_RETURN) = i;
3007 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3008 static void VM_SV_trailparticles (void)
3010 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
3012 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3015 MSG_WriteByte(&sv.datagram, svc_trailparticles);
3016 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
3017 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
3018 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
3019 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
3020 SV_FlushBroadcastMessages();
3023 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
3024 static void VM_SV_pointparticles (void)
3026 int effectnum, count;
3028 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
3030 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3033 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
3034 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
3035 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
3036 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
3037 if (count == 1 && !VectorLength2(vel))
3040 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
3041 MSG_WriteShort(&sv.datagram, effectnum);
3042 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3046 // 1+2+12+12+2=29 bytes
3047 MSG_WriteByte(&sv.datagram, svc_pointparticles);
3048 MSG_WriteShort(&sv.datagram, effectnum);
3049 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3050 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
3051 MSG_WriteShort(&sv.datagram, count);
3054 SV_FlushBroadcastMessages();
3057 //PF_setpause, // void(float pause) setpause = #531;
3058 static void VM_SV_setpause(void) {
3060 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
3061 if (pauseValue != 0) { //pause the game
3063 sv.pausedstart = Sys_DoubleTime();
3064 } else { //disable pause, in case it was enabled
3065 if (sv.paused != 0) {
3070 // send notification to all clients
3071 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
3072 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
3075 prvm_builtin_t vm_sv_builtins[] = {
3076 NULL, // #0 NULL function (not callable) (QUAKE)
3077 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3078 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3079 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3080 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3081 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3082 VM_break, // #6 void() break (QUAKE)
3083 VM_random, // #7 float() random (QUAKE)
3084 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3085 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3086 VM_error, // #10 void(string e) error (QUAKE)
3087 VM_objerror, // #11 void(string e) objerror (QUAKE)
3088 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3089 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3090 VM_spawn, // #14 entity() spawn (QUAKE)
3091 VM_remove, // #15 void(entity e) remove (QUAKE)
3092 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3093 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3094 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3095 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3096 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3097 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3098 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3099 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3100 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3101 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3102 VM_ftos, // #26 string(float f) ftos (QUAKE)
3103 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3104 VM_coredump, // #28 void() coredump (QUAKE)
3105 VM_traceon, // #29 void() traceon (QUAKE)
3106 VM_traceoff, // #30 void() traceoff (QUAKE)
3107 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3108 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3109 NULL, // #33 (QUAKE)
3110 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3111 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3112 VM_rint, // #36 float(float v) rint (QUAKE)
3113 VM_floor, // #37 float(float v) floor (QUAKE)
3114 VM_ceil, // #38 float(float v) ceil (QUAKE)
3115 NULL, // #39 (QUAKE)
3116 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3117 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3118 NULL, // #42 (QUAKE)
3119 VM_fabs, // #43 float(float f) fabs (QUAKE)
3120 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3121 VM_cvar, // #45 float(string s) cvar (QUAKE)
3122 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3123 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3124 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3125 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3126 NULL, // #50 (QUAKE)
3127 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3128 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3129 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3130 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3131 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3132 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3133 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3134 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3135 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3136 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3137 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3138 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3139 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3140 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3141 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3142 NULL, // #66 (QUAKE)
3143 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3144 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3145 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3146 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3147 NULL, // #71 (QUAKE)
3148 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3149 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3150 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3151 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3152 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3153 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3154 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3155 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3156 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3157 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3158 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3159 NULL, // #83 (QUAKE)
3160 NULL, // #84 (QUAKE)
3161 NULL, // #85 (QUAKE)
3162 NULL, // #86 (QUAKE)
3163 NULL, // #87 (QUAKE)
3164 NULL, // #88 (QUAKE)
3165 NULL, // #89 (QUAKE)
3166 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3167 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3168 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3169 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3170 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3171 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3172 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3173 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3174 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3175 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3176 // FrikaC and Telejano range #100-#199
3187 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3188 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3189 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3190 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3191 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3192 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3193 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3194 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3195 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3196 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3277 // FTEQW range #200-#299
3296 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3299 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3300 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3301 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3302 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3303 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3304 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3305 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3306 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3307 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3308 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3310 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3318 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3378 // CSQC range #300-#399
3379 NULL, // #300 void() clearscene (EXT_CSQC)
3380 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3381 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3382 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3383 NULL, // #304 void() renderscene (EXT_CSQC)
3384 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3385 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3386 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3387 NULL, // #308 void() R_EndPolygon
3389 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3390 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3394 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3395 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3396 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3397 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3398 NULL, // #319 void(string name) freepic (EXT_CSQC)
3399 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3400 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3401 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3402 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3403 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3404 NULL, // #325 void(void) drawresetcliparea
3409 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3410 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3411 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3412 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3413 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3414 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3415 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3416 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3417 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3418 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3419 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3420 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3421 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3422 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3423 NULL, // #344 vector() getmousepos (EXT_CSQC)
3424 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3425 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3426 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3427 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3428 NULL, // #349 float() isdemo (EXT_CSQC)
3429 VM_isserver, // #350 float() isserver (EXT_CSQC)
3430 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3431 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3432 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3433 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3439 NULL, // #360 float() readbyte (EXT_CSQC)
3440 NULL, // #361 float() readchar (EXT_CSQC)
3441 NULL, // #362 float() readshort (EXT_CSQC)
3442 NULL, // #363 float() readlong (EXT_CSQC)
3443 NULL, // #364 float() readcoord (EXT_CSQC)
3444 NULL, // #365 float() readangle (EXT_CSQC)
3445 NULL, // #366 string() readstring (EXT_CSQC)
3446 NULL, // #367 float() readfloat (EXT_CSQC)
3479 // LordHavoc's range #400-#499
3480 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3481 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3482 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3483 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3484 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3485 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3486 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3487 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3488 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)
3489 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3490 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3491 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3492 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3493 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3494 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3495 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3496 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3497 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3498 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3499 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3500 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3501 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3502 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3503 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3504 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3505 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3506 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3507 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3508 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3509 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3510 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3511 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3512 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3513 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3514 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3515 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3516 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3517 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3518 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3519 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3520 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3521 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3522 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3523 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3524 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3525 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3526 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3527 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3528 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3529 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3530 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3531 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3532 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3533 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3534 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3535 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3536 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3537 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3539 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3540 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3541 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3542 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3543 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3544 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3545 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3546 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3547 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3548 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3549 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3551 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3552 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3553 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3554 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3555 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3556 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3557 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3558 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3559 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3560 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3561 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3562 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3563 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3564 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3565 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3566 VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3574 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3575 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3576 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3577 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3578 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3579 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3580 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3581 VM_SV_WritePicture, // #501
3583 VM_whichpack, // #503 string(string) whichpack = #503;
3590 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3591 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3592 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3593 VM_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET)
3594 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3595 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3596 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3597 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3598 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3599 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3609 VM_loadfromdata, // #529
3610 VM_loadfromfile, // #530
3611 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3685 VM_callfunction, // #605
3686 VM_writetofile, // #606
3687 VM_isfunction, // #607
3693 VM_parseentitydata, // #613
3704 VM_getextresponse, // #624 string getextresponse(void)
3708 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3710 void VM_SV_Cmd_Init(void)
3715 void VM_SV_Cmd_Reset(void)
3717 World_End(&sv.world);
3718 if(prog->funcoffsets.SV_Shutdown)
3720 func_t s = prog->funcoffsets.SV_Shutdown;
3721 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3722 PRVM_ExecuteProgram(s,"SV_Shutdown() required");