6 //============================================================================
11 char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
22 "DP_CSQC_ENTITYNOCULL "
23 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
24 "DP_CSQC_MULTIFRAME_INTERPOLATION "
25 "DP_CSQC_SPAWNPARTICLE "
41 "DP_ENT_CUSTOMCOLORMAP "
42 "DP_ENT_EXTERIORMODELTOCLIENT "
45 "DP_ENT_LOWPRECISION "
49 "DP_GFX_EXTERNALTEXTURES "
50 "DP_GFX_EXTERNALTEXTURES_PERMAP "
52 "DP_GFX_MODEL_INTERPOLATION "
53 "DP_GFX_QUAKE3MODELTAGS "
57 "DP_HALFLIFE_MAP_CVAR "
60 "DP_LIGHTSTYLE_STATICVALUE "
64 "DP_MOVETYPEBOUNCEMISSILE "
67 "DP_QC_ASINACOSATANATAN2TAN "
73 "DP_QC_CVAR_DEFSTRING "
74 "DP_QC_CVAR_DESCRIPTION "
81 "DP_QC_EXTRESPONSEPACKET "
83 "DP_QC_FINDCHAINFLAGS "
84 "DP_QC_FINDCHAINFLOAT "
85 "DP_QC_FINDCHAIN_TOFIELD "
91 "DP_QC_GETSURFACEPOINTATTRIBUTE "
93 "DP_QC_GETTAGINFO_BONEPROPERTIES "
95 "DP_QC_GETTIME_CDTRACK "
98 "DP_QC_MULTIPLETEMPSTRINGS "
99 "DP_QC_NUM_FOR_EDICT "
101 "DP_QC_SINCOSSQRTPOW "
103 "DP_QC_STRINGBUFFERS "
104 "DP_QC_STRINGBUFFERS_CVARLIST "
105 "DP_QC_STRINGCOLORFUNCTIONS "
106 "DP_QC_STRING_CASE_FUNCTIONS "
108 "DP_QC_TOKENIZEBYSEPARATOR "
109 "DP_QC_TOKENIZE_CONSOLE "
112 "DP_QC_TRACE_MOVETYPE_HITMODEL "
113 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
114 "DP_QC_UNLIMITEDTEMPSTRINGS "
117 "DP_QC_VECTOANGLES_WITH_ROLL "
118 "DP_QC_VECTORVECTORS "
125 "DP_SKELETONOBJECTS "
126 "DP_SND_DIRECTIONLESSATTNNONE "
134 "DP_SV_BOUNCEFACTOR "
135 "DP_SV_CLIENTCOLORS "
138 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
139 "DP_SV_DRAWONLYTOCLIENT "
142 "DP_SV_ENTITYCONTENTSTRANSITION "
143 "DP_SV_MODELFLAGS_AS_EFFECTS "
144 "DP_SV_MOVETYPESTEP_LANDEVENT "
146 "DP_SV_NODRAWTOCLIENT "
147 "DP_SV_ONENTITYNOSPAWNFUNCTION "
148 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
150 "DP_SV_PLAYERPHYSICS "
151 "DP_SV_POINTPARTICLES "
153 "DP_SV_PRECACHEANYTIME "
157 "DP_SV_ROTATINGBMODEL "
161 "DP_SV_SPAWNFUNC_PREFIX "
162 "DP_SV_WRITEPICTURE "
163 "DP_SV_WRITEUNTERMINATEDSTRING "
167 "DP_TE_EXPLOSIONRGB "
169 "DP_TE_PARTICLECUBE "
170 "DP_TE_PARTICLERAIN "
171 "DP_TE_PARTICLESNOW "
173 "DP_TE_QUADEFFECTS1 "
176 "DP_TE_STANDARDEFFECTBUILTINS "
177 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
181 "FTE_CSQC_SKELETONOBJECTS "
184 "KRIMZON_SV_PARSECLIENTCOMMAND "
187 "NEXUIZ_PLAYERMODEL "
189 "PRYDON_CLIENTCURSOR "
190 "TENEBRAE_GFX_DLIGHTS "
193 //"EXT_CSQC " // not ready yet
200 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.
202 setorigin (entity, origin)
205 static void VM_SV_setorigin (void)
210 VM_SAFEPARMCOUNT(2, VM_setorigin);
212 e = PRVM_G_EDICT(OFS_PARM0);
213 if (e == prog->edicts)
215 VM_Warning("setorigin: can not modify world entity\n");
218 if (e->priv.server->free)
220 VM_Warning("setorigin: can not modify free entity\n");
223 org = PRVM_G_VECTOR(OFS_PARM1);
224 VectorCopy (org, e->fields.server->origin);
228 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
229 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
233 for (i=0 ; i<3 ; i++)
235 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
237 // set derived values
238 VectorCopy (min, e->fields.server->mins);
239 VectorCopy (max, e->fields.server->maxs);
240 VectorSubtract (max, min, e->fields.server->size);
249 the size box is rotated by the current angle
250 LordHavoc: no it isn't...
252 setsize (entity, minvector, maxvector)
255 static void VM_SV_setsize (void)
260 VM_SAFEPARMCOUNT(3, VM_setsize);
262 e = PRVM_G_EDICT(OFS_PARM0);
263 if (e == prog->edicts)
265 VM_Warning("setsize: can not modify world entity\n");
268 if (e->priv.server->free)
270 VM_Warning("setsize: can not modify free entity\n");
273 min = PRVM_G_VECTOR(OFS_PARM1);
274 max = PRVM_G_VECTOR(OFS_PARM2);
275 SetMinMaxSize (e, min, max, false);
283 setmodel(entity, model)
286 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
287 static void VM_SV_setmodel (void)
293 VM_SAFEPARMCOUNT(2, VM_setmodel);
295 e = PRVM_G_EDICT(OFS_PARM0);
296 if (e == prog->edicts)
298 VM_Warning("setmodel: can not modify world entity\n");
301 if (e->priv.server->free)
303 VM_Warning("setmodel: can not modify free entity\n");
306 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
307 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
308 e->fields.server->modelindex = i;
310 mod = SV_GetModelByIndex(i);
314 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
315 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
317 SetMinMaxSize (e, quakemins, quakemaxs, true);
320 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
327 single print to a specific client
329 sprint(clientent, value)
332 static void VM_SV_sprint (void)
336 char string[VM_STRINGTEMP_LENGTH];
338 VM_VarString(1, string, sizeof(string));
340 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
342 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
343 // LordHavoc: div0 requested that sprintto world operate like print
350 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
352 VM_Warning("tried to centerprint to a non-client\n");
356 client = svs.clients + entnum-1;
357 if (!client->netconnection)
360 MSG_WriteChar(&client->netconnection->message,svc_print);
361 MSG_WriteString(&client->netconnection->message, string);
369 single print to a specific client
371 centerprint(clientent, value)
374 static void VM_SV_centerprint (void)
378 char string[VM_STRINGTEMP_LENGTH];
380 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
382 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
384 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
386 VM_Warning("tried to centerprint to a non-client\n");
390 client = svs.clients + entnum-1;
391 if (!client->netconnection)
394 VM_VarString(1, string, sizeof(string));
395 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
396 MSG_WriteString(&client->netconnection->message, string);
403 particle(origin, color, count)
406 static void VM_SV_particle (void)
412 VM_SAFEPARMCOUNT(4, VM_SV_particle);
414 org = PRVM_G_VECTOR(OFS_PARM0);
415 dir = PRVM_G_VECTOR(OFS_PARM1);
416 color = PRVM_G_FLOAT(OFS_PARM2);
417 count = PRVM_G_FLOAT(OFS_PARM3);
418 SV_StartParticle (org, dir, (int)color, (int)count);
428 static void VM_SV_ambientsound (void)
432 float vol, attenuation;
435 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
437 pos = PRVM_G_VECTOR (OFS_PARM0);
438 samp = PRVM_G_STRING(OFS_PARM1);
439 vol = PRVM_G_FLOAT(OFS_PARM2);
440 attenuation = PRVM_G_FLOAT(OFS_PARM3);
442 // check to see if samp was properly precached
443 soundnum = SV_SoundIndex(samp, 1);
451 // add an svc_spawnambient command to the level signon packet
454 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
456 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
458 MSG_WriteVector(&sv.signon, pos, sv.protocol);
460 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
461 MSG_WriteShort (&sv.signon, soundnum);
463 MSG_WriteByte (&sv.signon, soundnum);
465 MSG_WriteByte (&sv.signon, (int)(vol*255));
466 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
474 Each entity can have eight independant sound sources, like voice,
477 Channel 0 is an auto-allocate channel, the others override anything
478 already running on that entity/channel pair.
480 An attenuation of 0 will play full volume everywhere in the level.
481 Larger attenuations will drop off.
485 static void VM_SV_sound (void)
489 prvm_edict_t *entity;
493 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
495 entity = PRVM_G_EDICT(OFS_PARM0);
496 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
497 sample = PRVM_G_STRING(OFS_PARM2);
498 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
499 attenuation = PRVM_G_FLOAT(OFS_PARM4);
502 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
506 if (volume < 0 || volume > 255)
508 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
512 if (attenuation < 0 || attenuation > 4)
514 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
518 if (channel < 0 || channel > 7)
520 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
524 SV_StartSound (entity, channel, sample, volume, attenuation);
531 Follows the same logic as VM_SV_sound, except instead of
532 an entity, an origin for the sound is provided, and channel
533 is omitted (since no entity is being tracked).
537 static void VM_SV_pointsound(void)
544 VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
546 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
547 sample = PRVM_G_STRING(OFS_PARM1);
548 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
549 attenuation = PRVM_G_FLOAT(OFS_PARM3);
551 if (volume < 0 || volume > 255)
553 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
557 if (attenuation < 0 || attenuation > 4)
559 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
563 SV_StartPointSound (org, sample, volume, attenuation);
570 Used for use tracing and shot targeting
571 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
572 if the tryents flag is set.
574 traceline (vector1, vector2, movetype, ignore)
577 static void VM_SV_traceline (void)
584 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
586 prog->xfunction->builtinsprofile += 30;
588 v1 = PRVM_G_VECTOR(OFS_PARM0);
589 v2 = PRVM_G_VECTOR(OFS_PARM1);
590 move = (int)PRVM_G_FLOAT(OFS_PARM2);
591 ent = PRVM_G_EDICT(OFS_PARM3);
593 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]))
594 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));
596 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
598 VM_SetTraceGlobals(&trace);
606 Used for use tracing and shot targeting
607 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
608 if the tryents flag is set.
610 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
613 // LordHavoc: added this for my own use, VERY useful, similar to traceline
614 static void VM_SV_tracebox (void)
616 float *v1, *v2, *m1, *m2;
621 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
623 prog->xfunction->builtinsprofile += 30;
625 v1 = PRVM_G_VECTOR(OFS_PARM0);
626 m1 = PRVM_G_VECTOR(OFS_PARM1);
627 m2 = PRVM_G_VECTOR(OFS_PARM2);
628 v2 = PRVM_G_VECTOR(OFS_PARM3);
629 move = (int)PRVM_G_FLOAT(OFS_PARM4);
630 ent = PRVM_G_EDICT(OFS_PARM5);
632 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]))
633 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));
635 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
637 VM_SetTraceGlobals(&trace);
640 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
645 vec3_t original_origin;
646 vec3_t original_velocity;
647 vec3_t original_angles;
648 vec3_t original_avelocity;
652 VectorCopy(tossent->fields.server->origin , original_origin );
653 VectorCopy(tossent->fields.server->velocity , original_velocity );
654 VectorCopy(tossent->fields.server->angles , original_angles );
655 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
657 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
658 if (val != NULL && val->_float != 0)
659 gravity = val->_float;
662 gravity *= sv_gravity.value * 0.025;
664 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
666 SV_CheckVelocity (tossent);
667 tossent->fields.server->velocity[2] -= gravity;
668 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
669 VectorScale (tossent->fields.server->velocity, 0.05, move);
670 VectorAdd (tossent->fields.server->origin, move, end);
671 trace = SV_TraceBox(tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
672 VectorCopy (trace.endpos, tossent->fields.server->origin);
673 tossent->fields.server->velocity[2] -= gravity;
675 if (trace.fraction < 1)
679 VectorCopy(original_origin , tossent->fields.server->origin );
680 VectorCopy(original_velocity , tossent->fields.server->velocity );
681 VectorCopy(original_angles , tossent->fields.server->angles );
682 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
687 static void VM_SV_tracetoss (void)
691 prvm_edict_t *ignore;
693 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
695 prog->xfunction->builtinsprofile += 600;
697 ent = PRVM_G_EDICT(OFS_PARM0);
698 if (ent == prog->edicts)
700 VM_Warning("tracetoss: can not use world entity\n");
703 ignore = PRVM_G_EDICT(OFS_PARM1);
705 trace = SV_Trace_Toss (ent, ignore);
707 VM_SetTraceGlobals(&trace);
710 //============================================================================
712 static int checkpvsbytes;
713 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
715 static int VM_SV_newcheckclient (int check)
721 // cycle to the next one
723 check = bound(1, check, svs.maxclients);
724 if (check == svs.maxclients)
732 prog->xfunction->builtinsprofile++;
734 if (i == svs.maxclients+1)
736 // look up the client's edict
737 ent = PRVM_EDICT_NUM(i);
738 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
739 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
741 // found a valid client (possibly the same one again)
745 // get the PVS for the entity
746 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
748 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
749 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
758 Returns a client (or object that has a client enemy) that would be a
761 If there is more than one valid option, they are cycled each frame
763 If (self.origin + self.viewofs) is not in the PVS of the current target,
764 it is not returned at all.
769 int c_invis, c_notvis;
770 static void VM_SV_checkclient (void)
772 prvm_edict_t *ent, *self;
775 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
777 // find a new check if on a new frame
778 if (sv.time - sv.lastchecktime >= 0.1)
780 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
781 sv.lastchecktime = sv.time;
784 // return check if it might be visible
785 ent = PRVM_EDICT_NUM(sv.lastcheck);
786 if (ent->priv.server->free || ent->fields.server->health <= 0)
788 VM_RETURN_EDICT(prog->edicts);
792 // if current entity can't possibly see the check entity, return 0
793 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
794 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
795 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
798 VM_RETURN_EDICT(prog->edicts);
802 // might be able to see it
804 VM_RETURN_EDICT(ent);
807 //============================================================================
813 Checks if an entity is in a point's PVS.
814 Should be fast but can be inexact.
816 float checkpvs(vector viewpos, entity viewee) = #240;
819 static void VM_SV_checkpvs (void)
822 prvm_edict_t *viewee;
827 unsigned char fatpvs[MAX_MAP_LEAFS/8];
830 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
831 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
832 viewee = PRVM_G_EDICT(OFS_PARM1);
834 if(viewee->priv.server->free)
836 VM_Warning("checkpvs: can not check free entity\n");
837 PRVM_G_FLOAT(OFS_RETURN) = 4;
842 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
844 // no PVS support on this worldmodel... darn
845 PRVM_G_FLOAT(OFS_RETURN) = 3;
848 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
851 // viewpos isn't in any PVS... darn
852 PRVM_G_FLOAT(OFS_RETURN) = 2;
855 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
857 // using fat PVS like FTEQW does (slow)
858 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
860 // no PVS support on this worldmodel... darn
861 PRVM_G_FLOAT(OFS_RETURN) = 3;
864 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
867 // viewpos isn't in any PVS... darn
868 PRVM_G_FLOAT(OFS_RETURN) = 2;
871 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
880 Sends text over to the client's execution buffer
882 stuffcmd (clientent, value, ...)
885 static void VM_SV_stuffcmd (void)
889 char string[VM_STRINGTEMP_LENGTH];
891 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
893 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
894 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
896 VM_Warning("Can't stuffcmd to a non-client\n");
900 VM_VarString(1, string, sizeof(string));
903 host_client = svs.clients + entnum-1;
904 Host_ClientCommands ("%s", string);
912 Returns a chain of entities that have origins within a spherical area
914 findradius (origin, radius)
917 static void VM_SV_findradius (void)
919 prvm_edict_t *ent, *chain;
920 vec_t radius, radius2;
921 vec3_t org, eorg, mins, maxs;
924 prvm_edict_t *touchedicts[MAX_EDICTS];
927 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
930 chainfield = PRVM_G_INT(OFS_PARM2);
932 chainfield = prog->fieldoffsets.chain;
934 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
936 chain = (prvm_edict_t *)prog->edicts;
938 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
939 radius = PRVM_G_FLOAT(OFS_PARM1);
940 radius2 = radius * radius;
942 mins[0] = org[0] - (radius + 1);
943 mins[1] = org[1] - (radius + 1);
944 mins[2] = org[2] - (radius + 1);
945 maxs[0] = org[0] + (radius + 1);
946 maxs[1] = org[1] + (radius + 1);
947 maxs[2] = org[2] + (radius + 1);
948 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
949 if (numtouchedicts > MAX_EDICTS)
951 // this never happens
952 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
953 numtouchedicts = MAX_EDICTS;
955 for (i = 0;i < numtouchedicts;i++)
957 ent = touchedicts[i];
958 prog->xfunction->builtinsprofile++;
959 // Quake did not return non-solid entities but darkplaces does
960 // (note: this is the reason you can't blow up fallen zombies)
961 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
963 // LordHavoc: compare against bounding box rather than center so it
964 // doesn't miss large objects, and use DotProduct instead of Length
965 // for a major speedup
966 VectorSubtract(org, ent->fields.server->origin, eorg);
967 if (sv_gameplayfix_findradiusdistancetobox.integer)
969 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
970 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
971 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
974 VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
975 if (DotProduct(eorg, eorg) < radius2)
977 PRVM_EDICTFIELDVALUE(ent,chainfield)->edict = PRVM_EDICT_TO_PROG(chain);
982 VM_RETURN_EDICT(chain);
985 static void VM_SV_precache_sound (void)
987 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
988 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
991 static void VM_SV_precache_model (void)
993 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
994 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
995 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1002 float(float yaw, float dist[, settrace]) walkmove
1005 static void VM_SV_walkmove (void)
1014 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1016 // assume failure if it returns early
1017 PRVM_G_FLOAT(OFS_RETURN) = 0;
1019 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1020 if (ent == prog->edicts)
1022 VM_Warning("walkmove: can not modify world entity\n");
1025 if (ent->priv.server->free)
1027 VM_Warning("walkmove: can not modify free entity\n");
1030 yaw = PRVM_G_FLOAT(OFS_PARM0);
1031 dist = PRVM_G_FLOAT(OFS_PARM1);
1032 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1034 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1037 yaw = yaw*M_PI*2 / 360;
1039 move[0] = cos(yaw)*dist;
1040 move[1] = sin(yaw)*dist;
1043 // save program state, because SV_movestep may call other progs
1044 oldf = prog->xfunction;
1045 oldself = prog->globals.server->self;
1047 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1050 // restore program state
1051 prog->xfunction = oldf;
1052 prog->globals.server->self = oldself;
1062 static void VM_SV_droptofloor (void)
1068 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1070 // assume failure if it returns early
1071 PRVM_G_FLOAT(OFS_RETURN) = 0;
1073 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1074 if (ent == prog->edicts)
1076 VM_Warning("droptofloor: can not modify world entity\n");
1079 if (ent->priv.server->free)
1081 VM_Warning("droptofloor: can not modify free entity\n");
1085 VectorCopy (ent->fields.server->origin, end);
1088 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1089 SV_UnstickEntity(ent);
1091 trace = SV_TraceBox(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1092 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1095 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]);
1096 VectorAdd(ent->fields.server->origin, offset, org);
1097 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1098 VectorSubtract(trace.endpos, offset, trace.endpos);
1099 if (trace.startsolid)
1101 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]);
1102 SV_UnstickEntity(ent);
1104 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1105 ent->fields.server->groundentity = 0;
1106 PRVM_G_FLOAT(OFS_RETURN) = 1;
1108 else if (trace.fraction < 1)
1110 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]);
1111 VectorCopy (trace.endpos, ent->fields.server->origin);
1112 SV_UnstickEntity(ent);
1114 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1115 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1116 PRVM_G_FLOAT(OFS_RETURN) = 1;
1117 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1118 ent->priv.server->suspendedinairflag = true;
1123 if (trace.fraction != 1)
1125 if (trace.fraction < 1)
1126 VectorCopy (trace.endpos, ent->fields.server->origin);
1128 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1129 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1130 PRVM_G_FLOAT(OFS_RETURN) = 1;
1131 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1132 ent->priv.server->suspendedinairflag = true;
1141 void(float style, string value) lightstyle
1144 static void VM_SV_lightstyle (void)
1151 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1153 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1154 val = PRVM_G_STRING(OFS_PARM1);
1156 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1157 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1160 // change the string in sv
1161 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1163 // send message to all clients on this server
1164 if (sv.state != ss_active)
1167 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1169 if (client->active && client->netconnection)
1171 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1172 MSG_WriteChar (&client->netconnection->message,style);
1173 MSG_WriteString (&client->netconnection->message, val);
1183 static void VM_SV_checkbottom (void)
1185 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1186 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1194 static void VM_SV_pointcontents (void)
1196 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1197 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1204 Pick a vector for the player to shoot along
1205 vector aim(entity, missilespeed)
1208 static void VM_SV_aim (void)
1210 prvm_edict_t *ent, *check, *bestent;
1211 vec3_t start, dir, end, bestdir;
1214 float dist, bestdist;
1217 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1219 // assume failure if it returns early
1220 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1221 // if sv_aim is so high it can't possibly accept anything, skip out early
1222 if (sv_aim.value >= 1)
1225 ent = PRVM_G_EDICT(OFS_PARM0);
1226 if (ent == prog->edicts)
1228 VM_Warning("aim: can not use world entity\n");
1231 if (ent->priv.server->free)
1233 VM_Warning("aim: can not use free entity\n");
1236 speed = PRVM_G_FLOAT(OFS_PARM1);
1238 VectorCopy (ent->fields.server->origin, start);
1241 // try sending a trace straight
1242 VectorCopy (prog->globals.server->v_forward, dir);
1243 VectorMA (start, 2048, dir, end);
1244 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1245 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1246 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1248 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1253 // try all possible entities
1254 VectorCopy (dir, bestdir);
1255 bestdist = sv_aim.value;
1258 check = PRVM_NEXT_EDICT(prog->edicts);
1259 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1261 prog->xfunction->builtinsprofile++;
1262 if (check->fields.server->takedamage != DAMAGE_AIM)
1266 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1267 continue; // don't aim at teammate
1268 for (j=0 ; j<3 ; j++)
1269 end[j] = check->fields.server->origin[j]
1270 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1271 VectorSubtract (end, start, dir);
1272 VectorNormalize (dir);
1273 dist = DotProduct (dir, prog->globals.server->v_forward);
1274 if (dist < bestdist)
1275 continue; // to far to turn
1276 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1277 if (tr.ent == check)
1278 { // can shoot at this one
1286 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1287 dist = DotProduct (dir, prog->globals.server->v_forward);
1288 VectorScale (prog->globals.server->v_forward, dist, end);
1290 VectorNormalize (end);
1291 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1295 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1300 ===============================================================================
1304 ===============================================================================
1307 #define MSG_BROADCAST 0 // unreliable to all
1308 #define MSG_ONE 1 // reliable to one (msg_entity)
1309 #define MSG_ALL 2 // reliable to all
1310 #define MSG_INIT 3 // write to the init string
1311 #define MSG_ENTITY 5
1313 sizebuf_t *WriteDest (void)
1319 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1323 return &sv.datagram;
1326 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1327 entnum = PRVM_NUM_FOR_EDICT(ent);
1328 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1330 VM_Warning ("WriteDest: tried to write to non-client\n");
1331 return &sv.reliable_datagram;
1334 return &svs.clients[entnum-1].netconnection->message;
1337 VM_Warning ("WriteDest: bad destination\n");
1339 return &sv.reliable_datagram;
1345 return sv.writeentitiestoclient_msg;
1351 static void VM_SV_WriteByte (void)
1353 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1354 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1357 static void VM_SV_WriteChar (void)
1359 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1360 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1363 static void VM_SV_WriteShort (void)
1365 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1366 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1369 static void VM_SV_WriteLong (void)
1371 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1372 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1375 static void VM_SV_WriteAngle (void)
1377 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1378 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1381 static void VM_SV_WriteCoord (void)
1383 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1384 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1387 static void VM_SV_WriteString (void)
1389 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1390 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1393 static void VM_SV_WriteUnterminatedString (void)
1395 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1396 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1399 static void VM_SV_WriteEntity (void)
1401 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1402 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1405 static void VM_SV_WriteByteINT (void)
1407 VM_SAFEPARMCOUNT(2, VM_SV_WriteByteINT);
1408 MSG_WriteByte (WriteDest(), PRVM_G_INT(OFS_PARM1));
1411 static void VM_SV_WriteCharINT (void)
1413 VM_SAFEPARMCOUNT(2, VM_SV_WriteCharINT);
1414 MSG_WriteChar (WriteDest(), PRVM_G_INT(OFS_PARM1));
1417 static void VM_SV_WriteShortINT (void)
1419 VM_SAFEPARMCOUNT(2, VM_SV_WriteShortINT);
1420 MSG_WriteShort (WriteDest(), PRVM_G_INT(OFS_PARM1));
1423 static void VM_SV_WriteLongINT (void)
1425 VM_SAFEPARMCOUNT(2, VM_SV_WriteLongINT);
1426 MSG_WriteLong (WriteDest(), PRVM_G_INT(OFS_PARM1));
1430 // writes a picture as at most size bytes of data
1432 // IMGNAME \0 SIZE(short) IMGDATA
1433 // if failed to read/compress:
1435 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1436 static void VM_SV_WritePicture (void)
1438 const char *imgname;
1442 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1444 imgname = PRVM_G_STRING(OFS_PARM1);
1445 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1449 MSG_WriteString(WriteDest(), imgname);
1450 if(Image_Compress(imgname, size, &buf, &size))
1453 MSG_WriteShort(WriteDest(), size);
1454 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1459 MSG_WriteShort(WriteDest(), 0);
1463 //////////////////////////////////////////////////////////
1465 static void VM_SV_makestatic (void)
1470 // allow 0 parameters due to an id1 qc bug in which this function is used
1471 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1472 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1474 if (prog->argc >= 1)
1475 ent = PRVM_G_EDICT(OFS_PARM0);
1477 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1478 if (ent == prog->edicts)
1480 VM_Warning("makestatic: can not modify world entity\n");
1483 if (ent->priv.server->free)
1485 VM_Warning("makestatic: can not modify free entity\n");
1490 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1495 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1496 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1497 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1499 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1501 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1502 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1503 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1507 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1508 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1509 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1512 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1513 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1514 for (i=0 ; i<3 ; i++)
1516 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1517 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1520 // throw the entity away now
1524 //=============================================================================
1531 static void VM_SV_setspawnparms (void)
1537 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1539 ent = PRVM_G_EDICT(OFS_PARM0);
1540 i = PRVM_NUM_FOR_EDICT(ent);
1541 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1543 Con_Print("tried to setspawnparms on a non-client\n");
1547 // copy spawn parms out of the client_t
1548 client = svs.clients + i-1;
1549 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1550 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1557 Returns a color vector indicating the lighting at the requested point.
1559 (Internal Operation note: actually measures the light beneath the point, just like
1560 the model lighting on the client)
1565 static void VM_SV_getlight (void)
1567 vec3_t ambientcolor, diffusecolor, diffusenormal;
1569 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1570 p = PRVM_G_VECTOR(OFS_PARM0);
1571 VectorClear(ambientcolor);
1572 VectorClear(diffusecolor);
1573 VectorClear(diffusenormal);
1574 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1575 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1576 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1581 unsigned char type; // 1/2/8 or other value if isn't used
1585 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1586 static int vm_customstats_last;
1588 void VM_CustomStats_Clear (void)
1592 Z_Free(vm_customstats);
1593 vm_customstats = NULL;
1594 vm_customstats_last = -1;
1598 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1606 for(i=0; i<vm_customstats_last+1 ;i++)
1608 if(!vm_customstats[i].type)
1610 switch(vm_customstats[i].type)
1612 //string as 16 bytes
1615 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1616 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1617 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1618 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1619 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1621 //float field sent as-is
1623 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1625 //integer value of float field
1627 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1635 // void(float index, float type, .void field) SV_AddStat = #232;
1636 // Set up an auto-sent player stat.
1637 // Client's get thier own fields sent to them. Index may not be less than 32.
1638 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1639 // 1: string (4 stats carrying a total of 16 charactures)
1640 // 2: float (one stat, float converted to an integer for transportation)
1641 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1642 static void VM_SV_AddStat (void)
1647 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1651 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1654 VM_Warning("PF_SV_AddStat: not enough memory\n");
1658 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1659 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1660 off = PRVM_G_INT (OFS_PARM2);
1665 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1668 if(i >= (MAX_CL_STATS-32))
1670 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1673 if(i > (MAX_CL_STATS-32-4) && type == 1)
1675 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1678 vm_customstats[i].type = type;
1679 vm_customstats[i].fieldoffset = off;
1680 if(vm_customstats_last < i)
1681 vm_customstats_last = i;
1688 copies data from one entity to another
1690 copyentity(src, dst)
1693 static void VM_SV_copyentity (void)
1695 prvm_edict_t *in, *out;
1696 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1697 in = PRVM_G_EDICT(OFS_PARM0);
1698 if (in == prog->edicts)
1700 VM_Warning("copyentity: can not read world entity\n");
1703 if (in->priv.server->free)
1705 VM_Warning("copyentity: can not read free entity\n");
1708 out = PRVM_G_EDICT(OFS_PARM1);
1709 if (out == prog->edicts)
1711 VM_Warning("copyentity: can not modify world entity\n");
1714 if (out->priv.server->free)
1716 VM_Warning("copyentity: can not modify free entity\n");
1719 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1728 sets the color of a client and broadcasts the update to all connected clients
1730 setcolor(clientent, value)
1733 static void VM_SV_setcolor (void)
1739 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1740 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1741 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1743 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1745 Con_Print("tried to setcolor a non-client\n");
1749 client = svs.clients + entnum-1;
1752 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1754 client->edict->fields.server->team = (i & 15) + 1;
1757 if (client->old_colors != client->colors)
1759 client->old_colors = client->colors;
1760 // send notification to all clients
1761 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1762 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1763 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1771 effect(origin, modelname, startframe, framecount, framerate)
1774 static void VM_SV_effect (void)
1778 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1779 s = PRVM_G_STRING(OFS_PARM1);
1782 VM_Warning("effect: no model specified\n");
1786 i = SV_ModelIndex(s, 1);
1789 VM_Warning("effect: model not precached\n");
1793 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1795 VM_Warning("effect: framecount < 1\n");
1799 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1801 VM_Warning("effect: framerate < 1\n");
1805 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));
1808 static void VM_SV_te_blood (void)
1810 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1811 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1813 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1814 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1816 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1817 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1818 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1820 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1821 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1822 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1824 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1825 SV_FlushBroadcastMessages();
1828 static void VM_SV_te_bloodshower (void)
1830 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1831 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1833 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1834 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1836 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1837 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1838 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1840 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1841 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1842 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1844 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1846 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1847 SV_FlushBroadcastMessages();
1850 static void VM_SV_te_explosionrgb (void)
1852 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1853 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1854 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1856 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1857 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1858 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1860 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1861 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1862 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1863 SV_FlushBroadcastMessages();
1866 static void VM_SV_te_particlecube (void)
1868 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1869 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1871 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1872 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1874 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1875 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1876 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1878 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1879 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1880 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1882 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1883 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1884 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1886 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1888 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1889 // gravity true/false
1890 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1892 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1893 SV_FlushBroadcastMessages();
1896 static void VM_SV_te_particlerain (void)
1898 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1899 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1901 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1902 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1912 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1913 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1914 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1916 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1918 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1919 SV_FlushBroadcastMessages();
1922 static void VM_SV_te_particlesnow (void)
1924 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1925 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1927 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1928 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1934 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1936 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1942 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1944 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1945 SV_FlushBroadcastMessages();
1948 static void VM_SV_te_spark (void)
1950 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1951 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1953 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1954 MSG_WriteByte(&sv.datagram, TE_SPARK);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1960 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1961 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1962 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1964 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1965 SV_FlushBroadcastMessages();
1968 static void VM_SV_te_gunshotquad (void)
1970 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1971 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1972 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1974 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1975 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1976 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1977 SV_FlushBroadcastMessages();
1980 static void VM_SV_te_spikequad (void)
1982 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1983 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1984 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1989 SV_FlushBroadcastMessages();
1992 static void VM_SV_te_superspikequad (void)
1994 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1995 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1996 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1998 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1999 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2000 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2001 SV_FlushBroadcastMessages();
2004 static void VM_SV_te_explosionquad (void)
2006 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2007 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2008 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2010 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2011 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2012 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2013 SV_FlushBroadcastMessages();
2016 static void VM_SV_te_smallflash (void)
2018 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2019 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2020 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2022 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2023 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2024 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2025 SV_FlushBroadcastMessages();
2028 static void VM_SV_te_customflash (void)
2030 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2031 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2033 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2034 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2036 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2037 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2038 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2040 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2042 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2044 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2045 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2046 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2047 SV_FlushBroadcastMessages();
2050 static void VM_SV_te_gunshot (void)
2052 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2053 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2054 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2056 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2058 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2059 SV_FlushBroadcastMessages();
2062 static void VM_SV_te_spike (void)
2064 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2065 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2066 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2068 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2069 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2070 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2071 SV_FlushBroadcastMessages();
2074 static void VM_SV_te_superspike (void)
2076 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2077 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2078 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2080 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2081 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2082 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2083 SV_FlushBroadcastMessages();
2086 static void VM_SV_te_explosion (void)
2088 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2089 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2090 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2092 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2093 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2094 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2095 SV_FlushBroadcastMessages();
2098 static void VM_SV_te_tarexplosion (void)
2100 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2101 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2102 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2104 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2105 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2106 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2107 SV_FlushBroadcastMessages();
2110 static void VM_SV_te_wizspike (void)
2112 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2113 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2114 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2116 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2117 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2118 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2119 SV_FlushBroadcastMessages();
2122 static void VM_SV_te_knightspike (void)
2124 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2125 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2126 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2128 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2129 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2130 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2131 SV_FlushBroadcastMessages();
2134 static void VM_SV_te_lavasplash (void)
2136 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2137 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2138 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2140 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2141 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2142 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2143 SV_FlushBroadcastMessages();
2146 static void VM_SV_te_teleport (void)
2148 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2149 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2150 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2152 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2153 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2154 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2155 SV_FlushBroadcastMessages();
2158 static void VM_SV_te_explosion2 (void)
2160 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2161 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2162 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2164 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2165 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2166 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2168 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2169 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2170 SV_FlushBroadcastMessages();
2173 static void VM_SV_te_lightning1 (void)
2175 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2176 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2177 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2179 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2181 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2182 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2183 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2185 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2186 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2187 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2188 SV_FlushBroadcastMessages();
2191 static void VM_SV_te_lightning2 (void)
2193 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2194 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2195 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2197 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2199 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2200 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2201 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2203 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2204 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2205 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2206 SV_FlushBroadcastMessages();
2209 static void VM_SV_te_lightning3 (void)
2211 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2212 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2213 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2215 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2217 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2218 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2219 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2221 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2222 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2223 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2224 SV_FlushBroadcastMessages();
2227 static void VM_SV_te_beam (void)
2229 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2230 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2231 MSG_WriteByte(&sv.datagram, TE_BEAM);
2233 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2235 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2236 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2237 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2239 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2240 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2241 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2242 SV_FlushBroadcastMessages();
2245 static void VM_SV_te_plasmaburn (void)
2247 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2248 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2249 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2250 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2251 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2252 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2253 SV_FlushBroadcastMessages();
2256 static void VM_SV_te_flamejet (void)
2258 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2259 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2260 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2262 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2263 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2264 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2266 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2267 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2268 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2270 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2271 SV_FlushBroadcastMessages();
2274 void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2277 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2279 bestdist = 1000000000;
2281 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2283 // clip original point to each triangle of the surface and find the
2284 // triangle that is closest
2285 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2286 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2287 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2288 TriangleNormal(v[0], v[1], v[2], facenormal);
2289 VectorNormalize(facenormal);
2290 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2291 VectorMA(p, offsetdist, facenormal, temp);
2292 for (j = 0, k = 2;j < 3;k = j, j++)
2294 VectorSubtract(v[k], v[j], edgenormal);
2295 CrossProduct(edgenormal, facenormal, sidenormal);
2296 VectorNormalize(sidenormal);
2297 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2299 VectorMA(temp, offsetdist, sidenormal, temp);
2301 dist = VectorDistance2(temp, p);
2302 if (bestdist > dist)
2305 VectorCopy(temp, out);
2310 #define getmodel SV_GetModelFromEdict
2312 static msurface_t *getsurface(dp_model_t *model, int surfacenum)
2314 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2316 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2320 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2321 static void VM_SV_getsurfacenumpoints(void)
2324 msurface_t *surface;
2325 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints);
2326 // return 0 if no such surface
2327 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2329 PRVM_G_FLOAT(OFS_RETURN) = 0;
2333 // note: this (incorrectly) assumes it is a simple polygon
2334 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2336 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2337 static void VM_SV_getsurfacepoint(void)
2341 msurface_t *surface;
2343 VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint);
2344 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2345 ed = PRVM_G_EDICT(OFS_PARM0);
2346 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2348 // note: this (incorrectly) assumes it is a simple polygon
2349 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2350 if (pointnum < 0 || pointnum >= surface->num_vertices)
2352 // FIXME: implement rotation/scaling
2353 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2355 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
2356 // float SPA_POSITION = 0;
2357 // float SPA_S_AXIS = 1;
2358 // float SPA_T_AXIS = 2;
2359 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2360 // float SPA_TEXCOORDS0 = 4;
2361 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2362 // float SPA_LIGHTMAP0_COLOR = 6;
2363 static void VM_SV_getsurfacepointattribute(void)
2367 msurface_t *surface;
2371 VM_SAFEPARMCOUNT(4, VM_SV_getsurfacepoint);
2372 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2373 ed = PRVM_G_EDICT(OFS_PARM0);
2374 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2376 // note: this (incorrectly) assumes it is a simple polygon
2377 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2378 if (pointnum < 0 || pointnum >= surface->num_vertices)
2380 // FIXME: implement rotation/scaling
2381 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
2383 switch( attributetype ) {
2384 // float SPA_POSITION = 0;
2386 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2388 // float SPA_S_AXIS = 1;
2390 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2392 // float SPA_T_AXIS = 2;
2394 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2396 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
2398 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
2400 // float SPA_TEXCOORDS0 = 4;
2402 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2403 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
2404 ret[0] = texcoord[0];
2405 ret[1] = texcoord[1];
2409 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
2411 float *ret = PRVM_G_VECTOR(OFS_RETURN);
2412 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
2413 ret[0] = texcoord[0];
2414 ret[1] = texcoord[1];
2418 // float SPA_LIGHTMAP0_COLOR = 6;
2420 // ignore alpha for now..
2421 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2424 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2428 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2429 static void VM_SV_getsurfacenormal(void)
2432 msurface_t *surface;
2434 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal);
2435 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2436 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2438 // FIXME: implement rotation/scaling
2439 // note: this (incorrectly) assumes it is a simple polygon
2440 // note: this only returns the first triangle, so it doesn't work very
2441 // well for curved surfaces or arbitrary meshes
2442 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);
2443 VectorNormalize(normal);
2444 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2446 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2447 static void VM_SV_getsurfacetexture(void)
2450 msurface_t *surface;
2451 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture);
2452 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2453 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2455 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2457 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2458 static void VM_SV_getsurfacenearpoint(void)
2460 int surfacenum, best;
2462 vec_t dist, bestdist;
2465 msurface_t *surface;
2467 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint);
2468 PRVM_G_FLOAT(OFS_RETURN) = -1;
2469 ed = PRVM_G_EDICT(OFS_PARM0);
2470 point = PRVM_G_VECTOR(OFS_PARM1);
2472 if (!ed || ed->priv.server->free)
2474 model = getmodel(ed);
2475 if (!model || !model->num_surfaces)
2478 // FIXME: implement rotation/scaling
2479 VectorSubtract(point, ed->fields.server->origin, p);
2481 bestdist = 1000000000;
2482 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2484 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2485 // first see if the nearest point on the surface's box is closer than the previous match
2486 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2487 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2488 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2489 dist = VectorLength2(clipped);
2490 if (dist < bestdist)
2492 // it is, check the nearest point on the actual geometry
2493 clippointtosurface(model, surface, p, clipped);
2494 VectorSubtract(clipped, p, clipped);
2495 dist += VectorLength2(clipped);
2496 if (dist < bestdist)
2498 // that's closer too, store it as the best match
2504 PRVM_G_FLOAT(OFS_RETURN) = best;
2506 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2507 static void VM_SV_getsurfaceclippedpoint(void)
2511 msurface_t *surface;
2513 VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint);
2514 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2515 ed = PRVM_G_EDICT(OFS_PARM0);
2516 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2518 // FIXME: implement rotation/scaling
2519 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2520 clippointtosurface(model, surface, p, out);
2521 // FIXME: implement rotation/scaling
2522 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2525 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2526 //this function originally written by KrimZon, made shorter by LordHavoc
2527 static void VM_SV_clientcommand (void)
2529 client_t *temp_client;
2531 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2533 //find client for this entity
2534 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2535 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2537 Con_Print("PF_clientcommand: entity is not a client\n");
2541 temp_client = host_client;
2542 host_client = svs.clients + i;
2543 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2544 host_client = temp_client;
2547 //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)
2548 static void VM_SV_setattachment (void)
2550 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2551 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2552 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2555 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2557 if (e == prog->edicts)
2559 VM_Warning("setattachment: can not modify world entity\n");
2562 if (e->priv.server->free)
2564 VM_Warning("setattachment: can not modify free entity\n");
2568 if (tagentity == NULL)
2569 tagentity = prog->edicts;
2571 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2573 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2575 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2578 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2580 model = SV_GetModelFromEdict(tagentity);
2583 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2585 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);
2588 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));
2592 /////////////////////////////////////////
2593 // DP_MD3_TAGINFO extension coded by VorteX
2595 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2599 i = (int)e->fields.server->modelindex;
2600 if (i < 1 || i >= MAX_MODELS)
2603 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)e->fields.server->skin, tagname);
2606 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2613 Matrix4x4_CreateIdentity(tag_localmatrix);
2615 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2617 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)e->fields.server->skin, e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2628 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2632 float pitchsign = 1;
2635 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2636 if (val && val->_float != 0)
2637 scale = val->_float;
2640 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);
2643 pitchsign = SV_GetPitchSign(ent);
2644 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);
2648 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2651 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->num_bones)
2653 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2654 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2655 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2656 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2658 *out = identitymatrix;
2662 // Warnings/errors code:
2663 // 0 - normal (everything all-right)
2666 // 3 - null or non-precached model
2667 // 4 - no tags with requested index
2668 // 5 - runaway loop at attachment chain
2669 extern cvar_t cl_bob;
2670 extern cvar_t cl_bobcycle;
2671 extern cvar_t cl_bobup;
2672 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2676 int modelindex, attachloop;
2677 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2680 *out = identitymatrix; // warnings and errors return identical matrix
2682 if (ent == prog->edicts)
2684 if (ent->priv.server->free)
2687 modelindex = (int)ent->fields.server->modelindex;
2688 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2691 model = SV_GetModelByIndex(modelindex);
2693 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2694 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2695 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2697 tagmatrix = identitymatrix;
2698 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2702 if (attachloop >= 256) // prevent runaway looping
2704 // apply transformation by child's tagindex on parent entity and then
2705 // by parent entity itself
2706 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2707 if (ret && attachloop == 0)
2709 SV_GetEntityMatrix(ent, &entitymatrix, false);
2710 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2711 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2712 // next iteration we process the parent entity
2713 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2715 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2716 ent = PRVM_EDICT_NUM(val->edict);
2723 // RENDER_VIEWMODEL magic
2724 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2726 Matrix4x4_Copy(&tagmatrix, out);
2727 ent = PRVM_EDICT_NUM(val->edict);
2729 SV_GetEntityMatrix(ent, &entitymatrix, true);
2730 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2733 // Cl_bob, ported from rendering code
2734 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2737 // LordHavoc: this code is *weird*, but not replacable (I think it
2738 // should be done in QC on the server, but oh well, quake is quake)
2739 // LordHavoc: figured out bobup: the time at which the sin is at 180
2740 // degrees (which allows lengthening or squishing the peak or valley)
2741 cycle = sv.time/cl_bobcycle.value;
2742 cycle -= (int)cycle;
2743 if (cycle < cl_bobup.value)
2744 cycle = sin(M_PI * cycle / cl_bobup.value);
2746 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2747 // bob is proportional to velocity in the xy plane
2748 // (don't count Z, or jumping messes it up)
2749 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;
2750 bob = bob*0.3 + bob*0.7*cycle;
2751 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2758 //float(entity ent, string tagname) gettagindex;
2760 static void VM_SV_gettagindex (void)
2763 const char *tag_name;
2766 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2768 ent = PRVM_G_EDICT(OFS_PARM0);
2769 tag_name = PRVM_G_STRING(OFS_PARM1);
2771 if (ent == prog->edicts)
2773 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2776 if (ent->priv.server->free)
2778 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2783 if (!SV_GetModelFromEdict(ent))
2784 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2787 tag_index = SV_GetTagIndex(ent, tag_name);
2789 if(developer.integer >= 100)
2790 Con_Printf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2792 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2795 //vector(entity ent, float tagindex) gettaginfo;
2796 static void VM_SV_gettaginfo (void)
2800 matrix4x4_t tag_matrix;
2801 matrix4x4_t tag_localmatrix;
2803 const char *tagname;
2806 vec3_t fo, le, up, trans;
2807 const dp_model_t *model;
2809 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2811 e = PRVM_G_EDICT(OFS_PARM0);
2812 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2814 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2815 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, le, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2816 VectorScale(le, -1, prog->globals.server->v_right);
2817 model = SV_GetModelFromEdict(e);
2818 VM_GenerateFrameGroupBlend(e->priv.server->framegroupblend, e);
2819 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
2820 VM_UpdateEdictSkeleton(e, model, e->priv.server->frameblend);
2821 SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2822 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2824 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_parent)))
2825 val->_float = parentindex;
2826 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_name)))
2827 val->string = tagname ? PRVM_SetTempString(tagname) : 0;
2828 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_offset)))
2829 VectorCopy(trans, val->vector);
2830 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_forward)))
2831 VectorCopy(fo, val->vector);
2832 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_right)))
2833 VectorScale(le, -1, val->vector);
2834 if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_up)))
2835 VectorCopy(up, val->vector);
2840 VM_Warning("gettagindex: can't affect world entity\n");
2843 VM_Warning("gettagindex: can't affect free entity\n");
2846 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2849 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2852 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2857 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2858 static void VM_SV_dropclient (void)
2861 client_t *oldhostclient;
2862 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2863 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2864 if (clientnum < 0 || clientnum >= svs.maxclients)
2866 VM_Warning("dropclient: not a client\n");
2869 if (!svs.clients[clientnum].active)
2871 VM_Warning("dropclient: that client slot is not connected\n");
2874 oldhostclient = host_client;
2875 host_client = svs.clients + clientnum;
2876 SV_DropClient(false);
2877 host_client = oldhostclient;
2880 //entity() spawnclient (DP_SV_BOTCLIENT)
2881 static void VM_SV_spawnclient (void)
2885 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2886 prog->xfunction->builtinsprofile += 2;
2888 for (i = 0;i < svs.maxclients;i++)
2890 if (!svs.clients[i].active)
2892 prog->xfunction->builtinsprofile += 100;
2893 SV_ConnectClient (i, NULL);
2894 // this has to be set or else ClientDisconnect won't be called
2895 // we assume the qc will call ClientConnect...
2896 svs.clients[i].clientconnectcalled = true;
2897 ed = PRVM_EDICT_NUM(i + 1);
2901 VM_RETURN_EDICT(ed);
2904 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2905 static void VM_SV_clienttype (void)
2908 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2909 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2910 if (clientnum < 0 || clientnum >= svs.maxclients)
2911 PRVM_G_FLOAT(OFS_RETURN) = 3;
2912 else if (!svs.clients[clientnum].active)
2913 PRVM_G_FLOAT(OFS_RETURN) = 0;
2914 else if (svs.clients[clientnum].netconnection)
2915 PRVM_G_FLOAT(OFS_RETURN) = 1;
2917 PRVM_G_FLOAT(OFS_RETURN) = 2;
2924 string(string key) serverkey
2927 void VM_SV_serverkey(void)
2929 char string[VM_STRINGTEMP_LENGTH];
2930 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2931 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2932 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2935 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2936 static void VM_SV_setmodelindex (void)
2941 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2943 e = PRVM_G_EDICT(OFS_PARM0);
2944 if (e == prog->edicts)
2946 VM_Warning("setmodelindex: can not modify world entity\n");
2949 if (e->priv.server->free)
2951 VM_Warning("setmodelindex: can not modify free entity\n");
2954 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2955 if (i <= 0 || i >= MAX_MODELS)
2957 VM_Warning("setmodelindex: invalid modelindex\n");
2960 if (!sv.model_precache[i][0])
2962 VM_Warning("setmodelindex: model not precached\n");
2966 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2967 e->fields.server->modelindex = i;
2969 mod = SV_GetModelByIndex(i);
2973 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2974 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2976 SetMinMaxSize (e, quakemins, quakemaxs, true);
2979 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2982 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2983 static void VM_SV_modelnameforindex (void)
2986 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2988 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2990 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2991 if (i <= 0 || i >= MAX_MODELS)
2993 VM_Warning("modelnameforindex: invalid modelindex\n");
2996 if (!sv.model_precache[i][0])
2998 VM_Warning("modelnameforindex: model not precached\n");
3002 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
3005 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
3006 static void VM_SV_particleeffectnum (void)
3009 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
3010 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
3013 PRVM_G_FLOAT(OFS_RETURN) = i;
3016 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3017 static void VM_SV_trailparticles (void)
3019 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
3021 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3024 MSG_WriteByte(&sv.datagram, svc_trailparticles);
3025 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
3026 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
3027 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
3028 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
3029 SV_FlushBroadcastMessages();
3032 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
3033 static void VM_SV_pointparticles (void)
3035 int effectnum, count;
3037 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
3039 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
3042 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
3043 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
3044 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
3045 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
3046 if (count == 1 && !VectorLength2(vel))
3049 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
3050 MSG_WriteShort(&sv.datagram, effectnum);
3051 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3055 // 1+2+12+12+2=29 bytes
3056 MSG_WriteByte(&sv.datagram, svc_pointparticles);
3057 MSG_WriteShort(&sv.datagram, effectnum);
3058 MSG_WriteVector(&sv.datagram, org, sv.protocol);
3059 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
3060 MSG_WriteShort(&sv.datagram, count);
3063 SV_FlushBroadcastMessages();
3066 //PF_setpause, // void(float pause) setpause = #531;
3067 static void VM_SV_setpause(void) {
3069 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
3070 if (pauseValue != 0) { //pause the game
3072 sv.pausedstart = Sys_DoubleTime();
3073 } else { //disable pause, in case it was enabled
3074 if (sv.paused != 0) {
3079 // send notification to all clients
3080 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
3081 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
3084 // #263 float(float modlindex) skel_create = #263; // (FTE_CSQC_SKELETONOBJECTS) create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex.
3085 static void VM_SV_skel_create(void)
3087 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3088 dp_model_t *model = SV_GetModelByIndex(modelindex);
3089 skeleton_t *skeleton;
3091 PRVM_G_FLOAT(OFS_RETURN) = 0;
3092 if (!model || !model->num_bones)
3094 for (i = 0;i < MAX_EDICTS;i++)
3095 if (!prog->skeletons[i])
3097 if (i == MAX_EDICTS)
3099 prog->skeletons[i] = skeleton = Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
3100 skeleton->model = model;
3101 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
3102 // initialize to identity matrices
3103 for (i = 0;i < skeleton->model->num_bones;i++)
3104 skeleton->relativetransforms[i] = identitymatrix;
3105 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
3108 // #264 float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // (FTE_CSQC_SKELETONOBJECTS) blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure
3109 static void VM_SV_skel_build(void)
3111 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3112 skeleton_t *skeleton;
3113 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
3114 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
3115 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
3116 int firstbone = PRVM_G_FLOAT(OFS_PARM4);
3117 int lastbone = PRVM_G_FLOAT(OFS_PARM5);
3118 dp_model_t *model = SV_GetModelByIndex(modelindex);
3123 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
3124 frameblend_t frameblend[MAX_FRAMEBLENDS];
3125 matrix4x4_t blendedmatrix;
3127 PRVM_G_FLOAT(OFS_RETURN) = 0;
3128 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3130 firstbone = max(0, firstbone);
3131 lastbone = min(lastbone, model->num_bones - 1);
3132 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3133 VM_GenerateFrameGroupBlend(framegroupblend, ed);
3134 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
3135 blendfrac = 1.0f - retainfrac;
3136 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
3137 frameblend[numblends].lerp *= blendfrac;
3138 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3140 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
3141 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
3142 for (blendindex = 0;blendindex < numblends;blendindex++)
3144 Matrix4x4_FromArray12FloatD3D(&matrix, model->data_poses + 12 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
3145 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
3147 skeleton->relativetransforms[bonenum] = blendedmatrix;
3149 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex;
3152 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3153 static void VM_SV_skel_get_numbones(void)
3155 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3156 skeleton_t *skeleton;
3157 PRVM_G_FLOAT(OFS_RETURN) = 0;
3158 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3160 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
3163 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
3164 static void VM_SV_skel_get_bonename(void)
3166 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3167 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3168 skeleton_t *skeleton;
3169 PRVM_G_INT(OFS_RETURN) = 0;
3170 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3172 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3174 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(skeleton->model->data_bones[bonenum].name);
3177 // #267 float(float skel, float bonenum) skel_get_boneparent = #267; // (FTE_CSQC_SKELETONOBJECTS) returns parent num for supplied bonenum, 0 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
3178 static void VM_SV_skel_get_boneparent(void)
3180 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3181 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3182 skeleton_t *skeleton;
3183 PRVM_G_FLOAT(OFS_RETURN) = 0;
3184 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3186 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3188 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
3191 // #268 float(float skel, string tagname) skel_find_bone = #268; // (FTE_CSQC_SKELETONOBJECTS) get number of bone with specified name, 0 on failure, tagindex (bonenum+1) on success, same as using gettagindex on the modelindex
3192 static void VM_SV_skel_find_bone(void)
3194 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3195 const char *tagname = PRVM_G_STRING(OFS_PARM1);
3196 skeleton_t *skeleton;
3197 PRVM_G_FLOAT(OFS_RETURN) = 0;
3198 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3200 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
3203 // #269 vector(float skel, float bonenum) skel_get_bonerel = #269; // (FTE_CSQC_SKELETONOBJECTS) get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone)
3204 static void VM_SV_skel_get_bonerel(void)
3206 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3207 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3208 skeleton_t *skeleton;
3210 vec3_t forward, left, up, origin;
3211 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3212 VectorClear(prog->globals.client->v_forward);
3213 VectorClear(prog->globals.client->v_right);
3214 VectorClear(prog->globals.client->v_up);
3215 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3217 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3219 matrix = skeleton->relativetransforms[bonenum];
3220 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3221 VectorCopy(forward, prog->globals.client->v_forward);
3222 VectorNegate(left, prog->globals.client->v_right);
3223 VectorCopy(up, prog->globals.client->v_up);
3224 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3227 // #270 vector(float skel, float bonenum) skel_get_boneabs = #270; // (FTE_CSQC_SKELETONOBJECTS) get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity)
3228 static void VM_SV_skel_get_boneabs(void)
3230 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3231 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3232 skeleton_t *skeleton;
3235 vec3_t forward, left, up, origin;
3236 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3237 VectorClear(prog->globals.client->v_forward);
3238 VectorClear(prog->globals.client->v_right);
3239 VectorClear(prog->globals.client->v_up);
3240 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3242 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3244 matrix = skeleton->relativetransforms[bonenum];
3245 // convert to absolute
3246 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3249 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3251 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3252 VectorCopy(forward, prog->globals.client->v_forward);
3253 VectorNegate(left, prog->globals.client->v_right);
3254 VectorCopy(up, prog->globals.client->v_up);
3255 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3258 // #271 void(float skel, float bonenum, vector org) skel_set_bone = #271; // (FTE_CSQC_SKELETONOBJECTS) set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
3259 static void VM_SV_skel_set_bone(void)
3261 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3262 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3263 vec3_t forward, left, up, origin;
3264 skeleton_t *skeleton;
3266 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3268 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3270 VectorCopy(prog->globals.client->v_forward, forward);
3271 VectorNegate(prog->globals.client->v_right, left);
3272 VectorCopy(prog->globals.client->v_up, up);
3273 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3274 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3275 skeleton->relativetransforms[bonenum] = matrix;
3278 // #272 void(float skel, float bonenum, vector org) skel_mul_bone = #272; // (FTE_CSQC_SKELETONOBJECTS) transform bone matrix (relative to its parent) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
3279 static void VM_SV_skel_mul_bone(void)
3281 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3282 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3283 vec3_t forward, left, up, origin;
3284 skeleton_t *skeleton;
3287 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3289 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3291 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3292 VectorCopy(prog->globals.client->v_forward, forward);
3293 VectorNegate(prog->globals.client->v_right, left);
3294 VectorCopy(prog->globals.client->v_up, up);
3295 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3296 temp = skeleton->relativetransforms[bonenum];
3297 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3300 // #273 void(float skel, float startbone, float endbone, vector org) skel_mul_bones = #273; // (FTE_CSQC_SKELETONOBJECTS) transform bone matrices (relative to their parents) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bones)
3301 static void VM_SV_skel_mul_bones(void)
3303 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3304 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3305 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3307 vec3_t forward, left, up, origin;
3308 skeleton_t *skeleton;
3311 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3313 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3314 VectorCopy(prog->globals.client->v_forward, forward);
3315 VectorNegate(prog->globals.client->v_right, left);
3316 VectorCopy(prog->globals.client->v_up, up);
3317 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3318 firstbone = max(0, firstbone);
3319 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3320 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3322 temp = skeleton->relativetransforms[bonenum];
3323 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3327 // #274 void(float skeldst, float skelsrc, float startbone, float endbone) skel_copybones = #274; // (FTE_CSQC_SKELETONOBJECTS) copy bone matrices (relative to their parents) from one skeleton to another, useful for copying a skeleton to a corpse
3328 static void VM_SV_skel_copybones(void)
3330 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3331 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3332 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3333 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3335 skeleton_t *skeletondst;
3336 skeleton_t *skeletonsrc;
3337 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3339 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3341 firstbone = max(0, firstbone);
3342 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3343 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3344 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3345 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3348 // #275 void(float skel) skel_delete = #275; // (FTE_CSQC_SKELETONOBJECTS) deletes skeleton at the beginning of the next frame (you can add the entity, delete the skeleton, renderscene, and it will still work)
3349 static void VM_SV_skel_delete(void)
3351 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3352 skeleton_t *skeleton;
3353 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3356 prog->skeletons[skeletonindex] = NULL;
3359 // #276 float(float modlindex, string framename) frameforname = #276; // (FTE_CSQC_SKELETONOBJECTS) finds number of a specified frame in the animation, returns -1 if no match found
3360 static void VM_SV_frameforname(void)
3362 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3363 dp_model_t *model = SV_GetModelByIndex(modelindex);
3364 const char *name = PRVM_G_STRING(OFS_PARM1);
3366 PRVM_G_FLOAT(OFS_RETURN) = -1;
3367 if (!model || !model->animscenes)
3369 for (i = 0;i < model->numframes;i++)
3371 if (!strcasecmp(model->animscenes[i].name, name))
3373 PRVM_G_FLOAT(OFS_RETURN) = i;
3379 // #277 float(float modlindex, float framenum) frameduration = #277; // (FTE_CSQC_SKELETONOBJECTS) returns the intended play time (in seconds) of the specified framegroup, if it does not exist the result is 0, if it is a single frame it may be a small value around 0.1 or 0.
3380 static void VM_SV_frameduration(void)
3382 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3383 dp_model_t *model = SV_GetModelByIndex(modelindex);
3384 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3385 PRVM_G_FLOAT(OFS_RETURN) = 0;
3386 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3388 if (model->animscenes[framenum].framerate)
3389 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3393 prvm_builtin_t vm_sv_builtins[] = {
3394 NULL, // #0 NULL function (not callable) (QUAKE)
3395 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3396 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3397 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3398 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3399 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3400 VM_break, // #6 void() break (QUAKE)
3401 VM_random, // #7 float() random (QUAKE)
3402 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3403 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3404 VM_error, // #10 void(string e) error (QUAKE)
3405 VM_objerror, // #11 void(string e) objerror (QUAKE)
3406 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3407 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3408 VM_spawn, // #14 entity() spawn (QUAKE)
3409 VM_remove, // #15 void(entity e) remove (QUAKE)
3410 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3411 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3412 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3413 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3414 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3415 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3416 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3417 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3418 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3419 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3420 VM_ftos, // #26 string(float f) ftos (QUAKE)
3421 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3422 VM_coredump, // #28 void() coredump (QUAKE)
3423 VM_traceon, // #29 void() traceon (QUAKE)
3424 VM_traceoff, // #30 void() traceoff (QUAKE)
3425 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3426 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3427 NULL, // #33 (QUAKE)
3428 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3429 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3430 VM_rint, // #36 float(float v) rint (QUAKE)
3431 VM_floor, // #37 float(float v) floor (QUAKE)
3432 VM_ceil, // #38 float(float v) ceil (QUAKE)
3433 NULL, // #39 (QUAKE)
3434 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3435 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3436 NULL, // #42 (QUAKE)
3437 VM_fabs, // #43 float(float f) fabs (QUAKE)
3438 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3439 VM_cvar, // #45 float(string s) cvar (QUAKE)
3440 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3441 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3442 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3443 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3444 NULL, // #50 (QUAKE)
3445 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3446 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3447 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3448 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3449 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3450 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3451 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3452 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3453 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3454 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3455 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3456 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3457 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3458 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3459 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3460 NULL, // #66 (QUAKE)
3461 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3462 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3463 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3464 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3465 NULL, // #71 (QUAKE)
3466 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3467 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3468 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3469 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3470 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3471 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3472 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3473 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3474 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3475 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3476 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3477 NULL, // #83 (QUAKE)
3478 NULL, // #84 (QUAKE)
3479 NULL, // #85 (QUAKE)
3480 NULL, // #86 (QUAKE)
3481 NULL, // #87 (QUAKE)
3482 NULL, // #88 (QUAKE)
3483 NULL, // #89 (QUAKE)
3484 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3485 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3486 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3487 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3488 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3489 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3490 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3491 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3492 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3493 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3494 // FrikaC and Telejano range #100-#199
3505 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3506 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3507 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3508 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3509 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3510 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3511 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3512 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3513 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3514 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3595 // FTEQW range #200-#299
3614 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3617 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3618 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3619 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3620 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3621 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3622 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3623 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3624 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3625 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3626 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3628 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3636 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3659 VM_SV_skel_create, // #263 float(float modlindex) skel_create = #263; // (DP_SKELETONOBJECTS) create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex.
3660 VM_SV_skel_build, // #264 float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // (DP_SKELETONOBJECTS) blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure
3661 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3662 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3663 VM_SV_skel_get_boneparent, // #267 float(float skel, float bonenum) skel_get_boneparent = #267; // (DP_SKELETONOBJECTS) returns parent num for supplied bonenum, -1 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
3664 VM_SV_skel_find_bone, // #268 float(float skel, string tagname) skel_find_bone = #268; // (DP_SKELETONOBJECTS) get number of bone with specified name, 0 on failure, tagindex (bonenum+1) on success, same as using gettagindex on the modelindex
3665 VM_SV_skel_get_bonerel, // #269 vector(float skel, float bonenum) skel_get_bonerel = #269; // (DP_SKELETONOBJECTS) get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone)
3666 VM_SV_skel_get_boneabs, // #270 vector(float skel, float bonenum) skel_get_boneabs = #270; // (DP_SKELETONOBJECTS) get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity)
3667 VM_SV_skel_set_bone, // #271 void(float skel, float bonenum, vector org) skel_set_bone = #271; // (DP_SKELETONOBJECTS) set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
3668 VM_SV_skel_mul_bone, // #272 void(float skel, float bonenum, vector org) skel_mul_bone = #272; // (DP_SKELETONOBJECTS) transform bone matrix (relative to its parent) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
3669 VM_SV_skel_mul_bones, // #273 void(float skel, float startbone, float endbone, vector org) skel_mul_bones = #273; // (DP_SKELETONOBJECTS) transform bone matrices (relative to their parents) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bones)
3670 VM_SV_skel_copybones, // #274 void(float skeldst, float skelsrc, float startbone, float endbone) skel_copybones = #274; // (DP_SKELETONOBJECTS) copy bone matrices (relative to their parents) from one skeleton to another, useful for copying a skeleton to a corpse
3671 VM_SV_skel_delete, // #275 void(float skel) skel_delete = #275; // (DP_SKELETONOBJECTS) deletes skeleton at the beginning of the next frame (you can add the entity, delete the skeleton, renderscene, and it will still work)
3672 VM_SV_frameforname, // #276 float(float modlindex, string framename) frameforname = #276; // (DP_SKELETONOBJECTS) finds number of a specified frame in the animation, returns -1 if no match found
3673 VM_SV_frameduration, // #277 float(float modlindex, float framenum) frameduration = #277; // (DP_SKELETONOBJECTS) returns the intended play time (in seconds) of the specified framegroup, if it does not exist the result is 0, if it is a single frame it may be a small value around 0.1 or 0.
3696 // CSQC range #300-#399
3697 NULL, // #300 void() clearscene (EXT_CSQC)
3698 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3699 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3700 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3701 NULL, // #304 void() renderscene (EXT_CSQC)
3702 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3703 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3704 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3705 NULL, // #308 void() R_EndPolygon
3707 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3708 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3712 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3713 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3714 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3715 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3716 NULL, // #319 void(string name) freepic (EXT_CSQC)
3717 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3718 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3719 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3720 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3721 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3722 NULL, // #325 void(void) drawresetcliparea
3727 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3728 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3729 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3730 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3731 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3732 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3733 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3734 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3735 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3736 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3737 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3738 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3739 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3740 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3741 NULL, // #344 vector() getmousepos (EXT_CSQC)
3742 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3743 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3744 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3745 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3746 NULL, // #349 float() isdemo (EXT_CSQC)
3747 VM_isserver, // #350 float() isserver (EXT_CSQC)
3748 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3749 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3750 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3751 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3757 NULL, // #360 float() readbyte (EXT_CSQC)
3758 NULL, // #361 float() readchar (EXT_CSQC)
3759 NULL, // #362 float() readshort (EXT_CSQC)
3760 NULL, // #363 float() readlong (EXT_CSQC)
3761 NULL, // #364 float() readcoord (EXT_CSQC)
3762 NULL, // #365 float() readangle (EXT_CSQC)
3763 NULL, // #366 string() readstring (EXT_CSQC)
3764 NULL, // #367 float() readfloat (EXT_CSQC)
3797 // LordHavoc's range #400-#499
3798 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3799 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3800 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3801 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3802 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3803 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3804 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3805 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3806 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)
3807 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3808 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3809 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3810 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3811 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3812 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3813 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3814 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3815 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3816 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3817 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3818 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3819 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3820 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3821 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3822 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3823 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3824 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3825 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3826 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3827 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3828 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3829 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3830 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3831 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3832 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3833 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3834 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3835 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3836 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3837 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3838 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3839 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3840 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3841 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3842 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3843 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3844 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3845 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3846 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3847 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3848 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3849 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3850 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3851 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3852 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3853 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3854 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3855 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3857 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3858 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3859 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3860 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3861 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3862 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3863 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3864 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3865 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3866 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3867 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3869 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3870 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3871 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3872 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3873 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3874 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3875 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3876 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3877 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3878 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3879 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3880 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3881 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3882 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3883 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3884 VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3892 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3893 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3894 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3895 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3896 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3897 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3898 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3899 VM_SV_WritePicture, // #501
3901 VM_whichpack, // #503 string(string) whichpack = #503;
3908 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3909 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3910 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3911 VM_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET)
3912 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3913 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3914 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3915 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3916 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3917 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3927 VM_loadfromdata, // #529
3928 VM_loadfromfile, // #530
3929 VM_SV_setpause, // #531 void(float pause) setpause = #531;
4003 VM_callfunction, // #605
4004 VM_writetofile, // #606
4005 VM_isfunction, // #607
4011 VM_parseentitydata, // #613
4022 VM_SV_getextresponse, // #624 string getextresponse(void)
4026 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
4028 void VM_SV_Cmd_Init(void)
4033 void VM_SV_Cmd_Reset(void)
4035 World_End(&sv.world);
4036 if(prog->funcoffsets.SV_Shutdown)
4038 func_t s = prog->funcoffsets.SV_Shutdown;
4039 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
4040 PRVM_ExecuteProgram(s,"SV_Shutdown() required");