6 //============================================================================
11 const char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
24 "DP_CSQC_ENTITYWORLDOBJECT "
25 "DP_CSQC_ENTITYMODELLIGHT "
26 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
28 "DP_CSQC_MINFPS_QUALITY "
29 "DP_CSQC_MULTIFRAME_INTERPOLATION "
30 "DP_CSQC_BOXPARTICLES "
31 "DP_CSQC_SPAWNPARTICLE "
32 "DP_CSQC_QUERYRENDERENTITY "
33 "DP_CSQC_ROTATEMOVES "
35 "DP_CSQC_V_CALCREFDEF_WIP1 "
47 "DP_EF_RESTARTANIM_BIT "
52 "DP_ENT_CUSTOMCOLORMAP "
53 "DP_ENT_EXTERIORMODELTOCLIENT "
56 "DP_ENT_LOWPRECISION "
58 "DP_ENT_TRAILEFFECTNUM "
60 "DP_GFX_EXTERNALTEXTURES "
61 "DP_GFX_EXTERNALTEXTURES_PERMAP "
63 "DP_GFX_MODEL_INTERPOLATION "
64 "DP_GFX_QUAKE3MODELTAGS "
68 "DP_GFX_FONTS_FREETYPE "
70 "DP_FONT_VARIABLEWIDTH "
72 "DP_HALFLIFE_MAP_CVAR "
75 "DP_LIGHTSTYLE_STATICVALUE "
79 "DP_MOVETYPEBOUNCEMISSILE "
80 "DP_MOVETYPEFLYWORLDONLY "
83 "DP_QC_ASINACOSATANATAN2TAN "
89 "DP_QC_CVAR_DEFSTRING "
90 "DP_QC_CVAR_DESCRIPTION "
94 "DP_QC_DIGEST_SHA256 "
99 "DP_QC_EXTRESPONSEPACKET "
101 "DP_QC_FINDCHAINFLAGS "
102 "DP_QC_FINDCHAINFLOAT "
103 "DP_QC_FINDCHAIN_TOFIELD "
109 "DP_QC_GETSURFACETRIANGLE "
110 "DP_QC_GETSURFACEPOINTATTRIBUTE "
112 "DP_QC_GETTAGINFO_BONEPROPERTIES "
114 "DP_QC_GETTIME_CDTRACK "
118 "DP_QC_MULTIPLETEMPSTRINGS "
119 "DP_QC_NUM_FOR_EDICT "
121 "DP_QC_SINCOSSQRTPOW "
124 "DP_QC_STRINGBUFFERS "
125 "DP_QC_STRINGBUFFERS_CVARLIST "
126 "DP_QC_STRINGCOLORFUNCTIONS "
127 "DP_QC_STRING_CASE_FUNCTIONS "
129 "DP_QC_TOKENIZEBYSEPARATOR "
130 "DP_QC_TOKENIZE_CONSOLE "
133 "DP_QC_TRACE_MOVETYPE_HITMODEL "
134 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
135 "DP_QC_UNLIMITEDTEMPSTRINGS "
139 "DP_QC_VECTOANGLES_WITH_ROLL "
140 "DP_QC_VECTORVECTORS "
147 "DP_SKELETONOBJECTS "
148 "DP_SND_DIRECTIONLESSATTNNONE "
150 "DP_SND_SOUND7_WIP1 "
151 "DP_SND_SOUND7_WIP2 "
155 "DP_SND_GETSOUNDTIME "
157 "DP_VIDEO_SUBTITLES "
161 "DP_SV_BOUNCEFACTOR "
162 "DP_SV_CLIENTCAMERA "
163 "DP_SV_CLIENTCOLORS "
166 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
167 "DP_SV_DISCARDABLEDEMO "
168 "DP_SV_DRAWONLYTOCLIENT "
171 "DP_SV_ENTITYCONTENTSTRANSITION "
172 "DP_SV_MODELFLAGS_AS_EFFECTS "
173 "DP_SV_MOVETYPESTEP_LANDEVENT "
175 "DP_SV_NODRAWTOCLIENT "
176 "DP_SV_ONENTITYNOSPAWNFUNCTION "
177 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
179 "DP_SV_PING_PACKETLOSS "
180 "DP_SV_PLAYERPHYSICS "
182 "DP_SV_POINTPARTICLES "
184 "DP_SV_PRECACHEANYTIME "
188 "DP_SV_ROTATINGBMODEL "
192 "DP_SV_SPAWNFUNC_PREFIX "
193 "DP_SV_WRITEPICTURE "
194 "DP_SV_WRITEUNTERMINATEDSTRING "
198 "DP_TE_EXPLOSIONRGB "
200 "DP_TE_PARTICLECUBE "
201 "DP_TE_PARTICLERAIN "
202 "DP_TE_PARTICLESNOW "
204 "DP_TE_QUADEFFECTS1 "
207 "DP_TE_STANDARDEFFECTBUILTINS "
208 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
212 "FTE_CSQC_SKELETONOBJECTS "
215 "KRIMZON_SV_PARSECLIENTCOMMAND "
218 "NEXUIZ_PLAYERMODEL "
220 "PRYDON_CLIENTCURSOR "
221 "TENEBRAE_GFX_DLIGHTS "
224 //"EXT_CSQC " // not ready yet
231 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.
233 setorigin (entity, origin)
236 static void VM_SV_setorigin(prvm_prog_t *prog)
241 VM_SAFEPARMCOUNT(2, VM_setorigin);
243 e = PRVM_G_EDICT(OFS_PARM0);
244 if (e == prog->edicts)
246 VM_Warning(prog, "setorigin: can not modify world entity\n");
249 if (e->priv.server->free)
251 VM_Warning(prog, "setorigin: can not modify free entity\n");
254 org = PRVM_G_VECTOR(OFS_PARM1);
255 VectorCopy (org, PRVM_serveredictvector(e, origin));
256 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
257 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
261 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
262 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qboolean rotate)
266 for (i=0 ; i<3 ; i++)
268 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
270 // set derived values
271 VectorCopy (min, PRVM_serveredictvector(e, mins));
272 VectorCopy (max, PRVM_serveredictvector(e, maxs));
273 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
282 the size box is rotated by the current angle
283 LordHavoc: no it isn't...
285 setsize (entity, minvector, maxvector)
288 static void VM_SV_setsize(prvm_prog_t *prog)
293 VM_SAFEPARMCOUNT(3, VM_setsize);
295 e = PRVM_G_EDICT(OFS_PARM0);
296 if (e == prog->edicts)
298 VM_Warning(prog, "setsize: can not modify world entity\n");
301 if (e->priv.server->free)
303 VM_Warning(prog, "setsize: can not modify free entity\n");
306 min = PRVM_G_VECTOR(OFS_PARM1);
307 max = PRVM_G_VECTOR(OFS_PARM2);
308 SetMinMaxSize(prog, e, min, max, false);
316 setmodel(entity, model)
319 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
320 static void VM_SV_setmodel(prvm_prog_t *prog)
326 VM_SAFEPARMCOUNT(2, VM_setmodel);
328 e = PRVM_G_EDICT(OFS_PARM0);
329 if (e == prog->edicts)
331 VM_Warning(prog, "setmodel: can not modify world entity\n");
334 if (e->priv.server->free)
336 VM_Warning(prog, "setmodel: can not modify free entity\n");
339 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
340 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
341 PRVM_serveredictfloat(e, modelindex) = i;
343 mod = SV_GetModelByIndex(i);
347 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
348 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
350 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
353 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
360 single print to a specific client
362 sprint(clientent, value)
365 static void VM_SV_sprint(prvm_prog_t *prog)
369 char string[VM_STRINGTEMP_LENGTH];
371 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
373 VM_VarString(prog, 1, string, sizeof(string));
375 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
376 // LordHavoc: div0 requested that sprintto world operate like print
383 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
385 VM_Warning(prog, "tried to centerprint to a non-client\n");
389 client = svs.clients + entnum-1;
390 if (!client->netconnection)
393 MSG_WriteChar(&client->netconnection->message,svc_print);
394 MSG_WriteString(&client->netconnection->message, string);
402 single print to a specific client
404 centerprint(clientent, value)
407 static void VM_SV_centerprint(prvm_prog_t *prog)
411 char string[VM_STRINGTEMP_LENGTH];
413 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
415 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
417 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
419 VM_Warning(prog, "tried to centerprint to a non-client\n");
423 client = svs.clients + entnum-1;
424 if (!client->netconnection)
427 VM_VarString(prog, 1, string, sizeof(string));
428 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
429 MSG_WriteString(&client->netconnection->message, string);
436 particle(origin, color, count)
439 static void VM_SV_particle(prvm_prog_t *prog)
445 VM_SAFEPARMCOUNT(4, VM_SV_particle);
447 org = PRVM_G_VECTOR(OFS_PARM0);
448 dir = PRVM_G_VECTOR(OFS_PARM1);
449 color = PRVM_G_FLOAT(OFS_PARM2);
450 count = PRVM_G_FLOAT(OFS_PARM3);
451 SV_StartParticle (org, dir, (int)color, (int)count);
461 static void VM_SV_ambientsound(prvm_prog_t *prog)
465 float vol, attenuation;
468 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
470 pos = PRVM_G_VECTOR (OFS_PARM0);
471 samp = PRVM_G_STRING(OFS_PARM1);
472 vol = PRVM_G_FLOAT(OFS_PARM2);
473 attenuation = PRVM_G_FLOAT(OFS_PARM3);
475 // check to see if samp was properly precached
476 soundnum = SV_SoundIndex(samp, 1);
484 // add an svc_spawnambient command to the level signon packet
487 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
489 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
491 MSG_WriteVector(&sv.signon, pos, sv.protocol);
493 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
494 MSG_WriteShort (&sv.signon, soundnum);
496 MSG_WriteByte (&sv.signon, soundnum);
498 MSG_WriteByte (&sv.signon, (int)(vol*255));
499 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
507 Each entity can have eight independant sound sources, like voice,
510 Channel 0 is an auto-allocate channel, the others override anything
511 already running on that entity/channel pair.
513 An attenuation of 0 will play full volume everywhere in the level.
514 Larger attenuations will drop off.
518 static void VM_SV_sound(prvm_prog_t *prog)
522 prvm_edict_t *entity;
528 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
530 entity = PRVM_G_EDICT(OFS_PARM0);
531 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
532 sample = PRVM_G_STRING(OFS_PARM2);
533 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
536 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
540 attenuation = PRVM_G_FLOAT(OFS_PARM4);
544 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
549 if(channel >= 8 && channel <= 15) // weird QW feature
551 flags |= CHANFLAG_RELIABLE;
556 flags = PRVM_G_FLOAT(OFS_PARM6);
558 if (volume < 0 || volume > 255)
560 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
564 if (attenuation < 0 || attenuation > 4)
566 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
570 channel = CHAN_USER2ENGINE(channel);
572 if (!IS_CHAN(channel))
574 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
578 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE, pitchchange);
585 Follows the same logic as VM_SV_sound, except instead of
586 an entity, an origin for the sound is provided, and channel
587 is omitted (since no entity is being tracked).
591 static void VM_SV_pointsound(prvm_prog_t *prog)
599 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
601 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
602 sample = PRVM_G_STRING(OFS_PARM1);
603 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
604 attenuation = PRVM_G_FLOAT(OFS_PARM3);
605 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
607 if (volume < 0 || volume > 255)
609 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
613 if (attenuation < 0 || attenuation > 4)
615 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
619 SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
626 Used for use tracing and shot targeting
627 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
628 if the tryents flag is set.
630 traceline (vector1, vector2, movetype, ignore)
633 static void VM_SV_traceline(prvm_prog_t *prog)
640 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
642 prog->xfunction->builtinsprofile += 30;
644 v1 = PRVM_G_VECTOR(OFS_PARM0);
645 v2 = PRVM_G_VECTOR(OFS_PARM1);
646 move = (int)PRVM_G_FLOAT(OFS_PARM2);
647 ent = PRVM_G_EDICT(OFS_PARM3);
649 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]))
650 prog->error_cmd("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
652 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
654 VM_SetTraceGlobals(prog, &trace);
662 Used for use tracing and shot targeting
663 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
664 if the tryents flag is set.
666 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
669 // LordHavoc: added this for my own use, VERY useful, similar to traceline
670 static void VM_SV_tracebox(prvm_prog_t *prog)
672 float *v1, *v2, *m1, *m2;
677 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
679 prog->xfunction->builtinsprofile += 30;
681 v1 = PRVM_G_VECTOR(OFS_PARM0);
682 m1 = PRVM_G_VECTOR(OFS_PARM1);
683 m2 = PRVM_G_VECTOR(OFS_PARM2);
684 v2 = PRVM_G_VECTOR(OFS_PARM3);
685 move = (int)PRVM_G_FLOAT(OFS_PARM4);
686 ent = PRVM_G_EDICT(OFS_PARM5);
688 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]))
689 prog->error_cmd("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", prog->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));
691 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
693 VM_SetTraceGlobals(prog, &trace);
696 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
701 vec3_t original_origin;
702 vec3_t original_velocity;
703 vec3_t original_angles;
704 vec3_t original_avelocity;
707 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
708 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
709 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
710 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
712 gravity = PRVM_serveredictfloat(tossent, gravity);
715 gravity *= sv_gravity.value * 0.025;
717 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
719 SV_CheckVelocity (tossent);
720 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
721 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
722 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
723 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
724 trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
725 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
726 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
728 if (trace.fraction < 1)
732 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
733 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
734 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
735 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
740 static void VM_SV_tracetoss(prvm_prog_t *prog)
744 prvm_edict_t *ignore;
746 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
748 prog->xfunction->builtinsprofile += 600;
750 ent = PRVM_G_EDICT(OFS_PARM0);
751 if (ent == prog->edicts)
753 VM_Warning(prog, "tracetoss: can not use world entity\n");
756 ignore = PRVM_G_EDICT(OFS_PARM1);
758 trace = SV_Trace_Toss(prog, ent, ignore);
760 VM_SetTraceGlobals(prog, &trace);
763 //============================================================================
765 static int checkpvsbytes;
766 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
768 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
774 // cycle to the next one
776 check = bound(1, check, svs.maxclients);
777 if (check == svs.maxclients)
785 prog->xfunction->builtinsprofile++;
787 if (i == svs.maxclients+1)
789 // look up the client's edict
790 ent = PRVM_EDICT_NUM(i);
791 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
792 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
794 // found a valid client (possibly the same one again)
798 // get the PVS for the entity
799 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
801 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
802 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
811 Returns a client (or object that has a client enemy) that would be a
814 If there is more than one valid option, they are cycled each frame
816 If (self.origin + self.viewofs) is not in the PVS of the current target,
817 it is not returned at all.
822 int c_invis, c_notvis;
823 static void VM_SV_checkclient(prvm_prog_t *prog)
825 prvm_edict_t *ent, *self;
828 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
830 // find a new check if on a new frame
831 if (sv.time - sv.lastchecktime >= 0.1)
833 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
834 sv.lastchecktime = sv.time;
837 // return check if it might be visible
838 ent = PRVM_EDICT_NUM(sv.lastcheck);
839 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
841 VM_RETURN_EDICT(prog->edicts);
845 // if current entity can't possibly see the check entity, return 0
846 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
847 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
848 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
851 VM_RETURN_EDICT(prog->edicts);
855 // might be able to see it
857 VM_RETURN_EDICT(ent);
860 //============================================================================
866 Checks if an entity is in a point's PVS.
867 Should be fast but can be inexact.
869 float checkpvs(vector viewpos, entity viewee) = #240;
872 static void VM_SV_checkpvs(prvm_prog_t *prog)
875 prvm_edict_t *viewee;
880 unsigned char fatpvs[MAX_MAP_LEAFS/8];
883 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
884 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
885 viewee = PRVM_G_EDICT(OFS_PARM1);
887 if(viewee->priv.server->free)
889 VM_Warning(prog, "checkpvs: can not check free entity\n");
890 PRVM_G_FLOAT(OFS_RETURN) = 4;
895 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
897 // no PVS support on this worldmodel... darn
898 PRVM_G_FLOAT(OFS_RETURN) = 3;
901 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
904 // viewpos isn't in any PVS... darn
905 PRVM_G_FLOAT(OFS_RETURN) = 2;
908 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
910 // using fat PVS like FTEQW does (slow)
911 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
913 // no PVS support on this worldmodel... darn
914 PRVM_G_FLOAT(OFS_RETURN) = 3;
917 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
920 // viewpos isn't in any PVS... darn
921 PRVM_G_FLOAT(OFS_RETURN) = 2;
924 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
933 Sends text over to the client's execution buffer
935 stuffcmd (clientent, value, ...)
938 static void VM_SV_stuffcmd(prvm_prog_t *prog)
942 char string[VM_STRINGTEMP_LENGTH];
944 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
946 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
947 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
949 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
953 VM_VarString(prog, 1, string, sizeof(string));
956 host_client = svs.clients + entnum-1;
957 Host_ClientCommands ("%s", string);
965 Returns a chain of entities that have origins within a spherical area
967 findradius (origin, radius)
970 static void VM_SV_findradius(prvm_prog_t *prog)
972 prvm_edict_t *ent, *chain;
973 vec_t radius, radius2;
974 vec3_t org, eorg, mins, maxs;
977 static prvm_edict_t *touchedicts[MAX_EDICTS];
980 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
983 chainfield = PRVM_G_INT(OFS_PARM2);
985 chainfield = prog->fieldoffsets.chain;
987 prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
989 chain = (prvm_edict_t *)prog->edicts;
991 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
992 radius = PRVM_G_FLOAT(OFS_PARM1);
993 radius2 = radius * radius;
995 mins[0] = org[0] - (radius + 1);
996 mins[1] = org[1] - (radius + 1);
997 mins[2] = org[2] - (radius + 1);
998 maxs[0] = org[0] + (radius + 1);
999 maxs[1] = org[1] + (radius + 1);
1000 maxs[2] = org[2] + (radius + 1);
1001 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1002 if (numtouchedicts > MAX_EDICTS)
1004 // this never happens
1005 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1006 numtouchedicts = MAX_EDICTS;
1008 for (i = 0;i < numtouchedicts;i++)
1010 ent = touchedicts[i];
1011 prog->xfunction->builtinsprofile++;
1012 // Quake did not return non-solid entities but darkplaces does
1013 // (note: this is the reason you can't blow up fallen zombies)
1014 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1016 // LordHavoc: compare against bounding box rather than center so it
1017 // doesn't miss large objects, and use DotProduct instead of Length
1018 // for a major speedup
1019 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1020 if (sv_gameplayfix_findradiusdistancetobox.integer)
1022 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1023 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1024 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1027 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1028 if (DotProduct(eorg, eorg) < radius2)
1030 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1035 VM_RETURN_EDICT(chain);
1038 static void VM_SV_precache_sound(prvm_prog_t *prog)
1040 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1041 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1044 static void VM_SV_precache_model(prvm_prog_t *prog)
1046 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1047 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1048 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1055 float(float yaw, float dist[, settrace]) walkmove
1058 static void VM_SV_walkmove(prvm_prog_t *prog)
1067 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1069 // assume failure if it returns early
1070 PRVM_G_FLOAT(OFS_RETURN) = 0;
1072 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1073 if (ent == prog->edicts)
1075 VM_Warning(prog, "walkmove: can not modify world entity\n");
1078 if (ent->priv.server->free)
1080 VM_Warning(prog, "walkmove: can not modify free entity\n");
1083 yaw = PRVM_G_FLOAT(OFS_PARM0);
1084 dist = PRVM_G_FLOAT(OFS_PARM1);
1085 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1087 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1090 yaw = yaw*M_PI*2 / 360;
1092 move[0] = cos(yaw)*dist;
1093 move[1] = sin(yaw)*dist;
1096 // save program state, because SV_movestep may call other progs
1097 oldf = prog->xfunction;
1098 oldself = PRVM_serverglobaledict(self);
1100 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1103 // restore program state
1104 prog->xfunction = oldf;
1105 PRVM_serverglobaledict(self) = oldself;
1116 static void VM_SV_droptofloor(prvm_prog_t *prog)
1122 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1124 // assume failure if it returns early
1125 PRVM_G_FLOAT(OFS_RETURN) = 0;
1127 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1128 if (ent == prog->edicts)
1130 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1133 if (ent->priv.server->free)
1135 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1139 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1142 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1143 if (sv_gameplayfix_unstickentities.integer)
1144 SV_UnstickEntity(ent);
1146 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1147 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1150 VectorSet(offset, 0.5f * (PRVM_serveredictvector(ent, mins)[0] + PRVM_serveredictvector(ent, maxs)[0]), 0.5f * (PRVM_serveredictvector(ent, mins)[1] + PRVM_serveredictvector(ent, maxs)[1]), PRVM_serveredictvector(ent, mins)[2]);
1151 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1152 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1153 VectorSubtract(trace.endpos, offset, trace.endpos);
1154 if (trace.startsolid)
1156 Con_DPrintf("droptofloor at %f %f %f - COULD NOT FIX BADLY PLACED ENTITY\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
1157 if (sv_gameplayfix_unstickentities.integer)
1158 SV_UnstickEntity(ent);
1160 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1161 PRVM_serveredictedict(ent, groundentity) = 0;
1162 PRVM_G_FLOAT(OFS_RETURN) = 1;
1164 else if (trace.fraction < 1)
1166 Con_DPrintf("droptofloor at %f %f %f - FIXED BADLY PLACED ENTITY\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
1167 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1168 if (sv_gameplayfix_unstickentities.integer)
1169 SV_UnstickEntity(ent);
1171 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1172 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1173 PRVM_G_FLOAT(OFS_RETURN) = 1;
1174 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1175 ent->priv.server->suspendedinairflag = true;
1180 if (trace.fraction != 1)
1182 if (trace.fraction < 1)
1183 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1185 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1186 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1187 PRVM_G_FLOAT(OFS_RETURN) = 1;
1188 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1189 ent->priv.server->suspendedinairflag = true;
1198 void(float style, string value) lightstyle
1201 static void VM_SV_lightstyle(prvm_prog_t *prog)
1208 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1210 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1211 val = PRVM_G_STRING(OFS_PARM1);
1213 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1214 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1217 // change the string in sv
1218 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1220 // send message to all clients on this server
1221 if (sv.state != ss_active)
1224 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1226 if (client->active && client->netconnection)
1228 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1229 MSG_WriteChar (&client->netconnection->message,style);
1230 MSG_WriteString (&client->netconnection->message, val);
1240 static void VM_SV_checkbottom(prvm_prog_t *prog)
1242 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1243 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1251 static void VM_SV_pointcontents(prvm_prog_t *prog)
1253 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1254 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1261 Pick a vector for the player to shoot along
1262 vector aim(entity, missilespeed)
1265 static void VM_SV_aim(prvm_prog_t *prog)
1267 prvm_edict_t *ent, *check, *bestent;
1268 vec3_t start, dir, end, bestdir;
1271 float dist, bestdist;
1274 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1276 // assume failure if it returns early
1277 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1278 // if sv_aim is so high it can't possibly accept anything, skip out early
1279 if (sv_aim.value >= 1)
1282 ent = PRVM_G_EDICT(OFS_PARM0);
1283 if (ent == prog->edicts)
1285 VM_Warning(prog, "aim: can not use world entity\n");
1288 if (ent->priv.server->free)
1290 VM_Warning(prog, "aim: can not use free entity\n");
1293 //speed = PRVM_G_FLOAT(OFS_PARM1);
1295 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1298 // try sending a trace straight
1299 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1300 VectorMA (start, 2048, dir, end);
1301 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1302 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1303 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1305 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1310 // try all possible entities
1311 VectorCopy (dir, bestdir);
1312 bestdist = sv_aim.value;
1315 check = PRVM_NEXT_EDICT(prog->edicts);
1316 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1318 prog->xfunction->builtinsprofile++;
1319 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1323 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1324 continue; // don't aim at teammate
1325 for (j=0 ; j<3 ; j++)
1326 end[j] = PRVM_serveredictvector(check, origin)[j]
1327 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1328 VectorSubtract (end, start, dir);
1329 VectorNormalize (dir);
1330 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1331 if (dist < bestdist)
1332 continue; // to far to turn
1333 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1334 if (tr.ent == check)
1335 { // can shoot at this one
1343 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1344 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1345 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1347 VectorNormalize (end);
1348 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1352 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1357 ===============================================================================
1361 ===============================================================================
1364 #define MSG_BROADCAST 0 // unreliable to all
1365 #define MSG_ONE 1 // reliable to one (msg_entity)
1366 #define MSG_ALL 2 // reliable to all
1367 #define MSG_INIT 3 // write to the init string
1368 #define MSG_ENTITY 5
1370 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1376 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1380 return &sv.datagram;
1383 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1384 entnum = PRVM_NUM_FOR_EDICT(ent);
1385 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1387 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1388 return &sv.reliable_datagram;
1391 return &svs.clients[entnum-1].netconnection->message;
1394 VM_Warning(prog, "WriteDest: bad destination\n");
1396 return &sv.reliable_datagram;
1402 return sv.writeentitiestoclient_msg;
1408 static void VM_SV_WriteByte(prvm_prog_t *prog)
1410 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1411 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1414 static void VM_SV_WriteChar(prvm_prog_t *prog)
1416 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1417 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1420 static void VM_SV_WriteShort(prvm_prog_t *prog)
1422 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1423 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1426 static void VM_SV_WriteLong(prvm_prog_t *prog)
1428 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1429 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1432 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1434 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1435 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1438 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1440 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1441 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1444 static void VM_SV_WriteString(prvm_prog_t *prog)
1446 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1447 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1450 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1452 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1453 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1457 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1459 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1460 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1463 // writes a picture as at most size bytes of data
1465 // IMGNAME \0 SIZE(short) IMGDATA
1466 // if failed to read/compress:
1468 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1469 static void VM_SV_WritePicture(prvm_prog_t *prog)
1471 const char *imgname;
1475 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1477 imgname = PRVM_G_STRING(OFS_PARM1);
1478 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1482 MSG_WriteString(WriteDest(prog), imgname);
1483 if(Image_Compress(imgname, size, &buf, &size))
1486 MSG_WriteShort(WriteDest(prog), size);
1487 SZ_Write(WriteDest(prog), (unsigned char *) buf, size);
1492 MSG_WriteShort(WriteDest(prog), 0);
1496 //////////////////////////////////////////////////////////
1498 static void VM_SV_makestatic(prvm_prog_t *prog)
1503 // allow 0 parameters due to an id1 qc bug in which this function is used
1504 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1505 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1507 if (prog->argc >= 1)
1508 ent = PRVM_G_EDICT(OFS_PARM0);
1510 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1511 if (ent == prog->edicts)
1513 VM_Warning(prog, "makestatic: can not modify world entity\n");
1516 if (ent->priv.server->free)
1518 VM_Warning(prog, "makestatic: can not modify free entity\n");
1523 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1528 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1529 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1530 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1532 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1534 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1535 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1536 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1540 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1541 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1542 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1545 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1546 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1547 for (i=0 ; i<3 ; i++)
1549 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1550 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1553 // throw the entity away now
1554 PRVM_ED_Free(prog, ent);
1557 //=============================================================================
1564 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1570 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1572 ent = PRVM_G_EDICT(OFS_PARM0);
1573 i = PRVM_NUM_FOR_EDICT(ent);
1574 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1576 Con_Print("tried to setspawnparms on a non-client\n");
1580 // copy spawn parms out of the client_t
1581 client = svs.clients + i-1;
1582 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1583 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1590 Returns a color vector indicating the lighting at the requested point.
1592 (Internal Operation note: actually measures the light beneath the point, just like
1593 the model lighting on the client)
1598 static void VM_SV_getlight(prvm_prog_t *prog)
1600 vec3_t ambientcolor, diffusecolor, diffusenormal;
1602 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1603 p = PRVM_G_VECTOR(OFS_PARM0);
1604 VectorClear(ambientcolor);
1605 VectorClear(diffusecolor);
1606 VectorClear(diffusenormal);
1607 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1608 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1609 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1614 unsigned char type; // 1/2/8 or other value if isn't used
1618 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1619 static int vm_customstats_last;
1621 void VM_CustomStats_Clear (void)
1625 Z_Free(vm_customstats);
1626 vm_customstats = NULL;
1627 vm_customstats_last = -1;
1631 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1633 prvm_prog_t *prog = SVVM_prog;
1640 for(i=0; i<vm_customstats_last+1 ;i++)
1642 if(!vm_customstats[i].type)
1644 switch(vm_customstats[i].type)
1646 //string as 16 bytes
1649 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1650 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1651 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1652 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1653 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1655 //float field sent as-is
1657 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1659 //integer value of float field
1661 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1669 // void(float index, float type, .void field) SV_AddStat = #232;
1670 // Set up an auto-sent player stat.
1671 // Client's get thier own fields sent to them. Index may not be less than 32.
1672 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1673 // 1: string (4 stats carrying a total of 16 charactures)
1674 // 2: float (one stat, float converted to an integer for transportation)
1675 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1676 static void VM_SV_AddStat(prvm_prog_t *prog)
1681 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1685 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1688 VM_Warning(prog, "PF_SV_AddStat: not enough memory\n");
1692 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1693 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1694 off = PRVM_G_INT (OFS_PARM2);
1699 VM_Warning(prog, "PF_SV_AddStat: index may not be less than 32\n");
1702 if(i >= (MAX_CL_STATS-32))
1704 VM_Warning(prog, "PF_SV_AddStat: index >= MAX_CL_STATS\n");
1707 if(i > (MAX_CL_STATS-32-4) && type == 1)
1709 VM_Warning(prog, "PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1712 vm_customstats[i].type = type;
1713 vm_customstats[i].fieldoffset = off;
1714 if(vm_customstats_last < i)
1715 vm_customstats_last = i;
1722 copies data from one entity to another
1724 copyentity(src, dst)
1727 static void VM_SV_copyentity(prvm_prog_t *prog)
1729 prvm_edict_t *in, *out;
1730 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1731 in = PRVM_G_EDICT(OFS_PARM0);
1732 if (in == prog->edicts)
1734 VM_Warning(prog, "copyentity: can not read world entity\n");
1737 if (in->priv.server->free)
1739 VM_Warning(prog, "copyentity: can not read free entity\n");
1742 out = PRVM_G_EDICT(OFS_PARM1);
1743 if (out == prog->edicts)
1745 VM_Warning(prog, "copyentity: can not modify world entity\n");
1748 if (out->priv.server->free)
1750 VM_Warning(prog, "copyentity: can not modify free entity\n");
1753 memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
1762 sets the color of a client and broadcasts the update to all connected clients
1764 setcolor(clientent, value)
1767 static void VM_SV_setcolor(prvm_prog_t *prog)
1772 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1773 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1774 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1776 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1778 Con_Print("tried to setcolor a non-client\n");
1782 client = svs.clients + entnum-1;
1785 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1786 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1789 if (client->old_colors != client->colors)
1791 client->old_colors = client->colors;
1792 // send notification to all clients
1793 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1794 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1795 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1803 effect(origin, modelname, startframe, framecount, framerate)
1806 static void VM_SV_effect(prvm_prog_t *prog)
1810 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1811 s = PRVM_G_STRING(OFS_PARM1);
1814 VM_Warning(prog, "effect: no model specified\n");
1818 i = SV_ModelIndex(s, 1);
1821 VM_Warning(prog, "effect: model not precached\n");
1825 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1827 VM_Warning(prog, "effect: framecount < 1\n");
1831 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1833 VM_Warning(prog, "effect: framerate < 1\n");
1837 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));
1840 static void VM_SV_te_blood(prvm_prog_t *prog)
1842 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1843 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1845 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1846 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1848 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1849 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1850 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1852 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1853 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1854 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1856 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1857 SV_FlushBroadcastMessages();
1860 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1862 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1863 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1865 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1866 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1868 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1869 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1870 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1873 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1874 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1876 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1878 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1879 SV_FlushBroadcastMessages();
1882 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1884 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1885 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1886 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1888 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1889 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1890 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1892 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1893 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1894 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1895 SV_FlushBroadcastMessages();
1898 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1900 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1901 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1903 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1904 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1911 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1912 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1914 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1915 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1916 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1918 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1920 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1921 // gravity true/false
1922 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1924 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1925 SV_FlushBroadcastMessages();
1928 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1930 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1931 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1933 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1934 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1936 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1941 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1942 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1944 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1945 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1948 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1950 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1951 SV_FlushBroadcastMessages();
1954 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1956 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1957 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1959 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1960 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1964 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1970 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1972 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1974 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1976 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1977 SV_FlushBroadcastMessages();
1980 static void VM_SV_te_spark(prvm_prog_t *prog)
1982 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1983 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1985 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1986 MSG_WriteByte(&sv.datagram, TE_SPARK);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1989 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1990 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1992 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1993 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1994 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1996 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1997 SV_FlushBroadcastMessages();
2000 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2002 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2003 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2004 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2006 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2007 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2008 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2009 SV_FlushBroadcastMessages();
2012 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2014 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2015 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2016 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2018 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2019 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2020 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2021 SV_FlushBroadcastMessages();
2024 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2026 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2027 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2028 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2030 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2031 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2032 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2033 SV_FlushBroadcastMessages();
2036 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2038 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2039 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2040 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2042 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2043 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2044 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2045 SV_FlushBroadcastMessages();
2048 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2050 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2051 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2052 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2054 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2055 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2056 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2057 SV_FlushBroadcastMessages();
2060 static void VM_SV_te_customflash(prvm_prog_t *prog)
2062 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2063 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2065 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2066 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
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);
2072 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2074 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2076 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2077 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2078 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2079 SV_FlushBroadcastMessages();
2082 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2084 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2085 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2086 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2088 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2089 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2090 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2091 SV_FlushBroadcastMessages();
2094 static void VM_SV_te_spike(prvm_prog_t *prog)
2096 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2097 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2098 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2100 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2101 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2102 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2103 SV_FlushBroadcastMessages();
2106 static void VM_SV_te_superspike(prvm_prog_t *prog)
2108 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2109 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2110 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2112 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2113 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2114 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2115 SV_FlushBroadcastMessages();
2118 static void VM_SV_te_explosion(prvm_prog_t *prog)
2120 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2121 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2122 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2124 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2125 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2126 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2127 SV_FlushBroadcastMessages();
2130 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2132 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2133 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2134 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2136 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2137 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2138 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2139 SV_FlushBroadcastMessages();
2142 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2144 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2145 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2146 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2148 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2149 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2150 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2151 SV_FlushBroadcastMessages();
2154 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2156 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2157 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2158 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2160 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2161 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2162 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2163 SV_FlushBroadcastMessages();
2166 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2168 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2169 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2170 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2172 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2173 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2174 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2175 SV_FlushBroadcastMessages();
2178 static void VM_SV_te_teleport(prvm_prog_t *prog)
2180 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2181 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2182 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2184 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2185 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2186 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2187 SV_FlushBroadcastMessages();
2190 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2192 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2193 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2194 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2196 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2197 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2198 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2200 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2201 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2202 SV_FlushBroadcastMessages();
2205 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2207 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2208 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2209 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2211 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2213 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2214 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2215 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2217 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2218 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2219 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2220 SV_FlushBroadcastMessages();
2223 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2225 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2226 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2227 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2229 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2231 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2232 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2235 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2236 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2237 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2238 SV_FlushBroadcastMessages();
2241 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2243 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2244 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2245 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2247 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2249 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2250 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2251 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2253 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2254 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2255 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2256 SV_FlushBroadcastMessages();
2259 static void VM_SV_te_beam(prvm_prog_t *prog)
2261 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2262 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2263 MSG_WriteByte(&sv.datagram, TE_BEAM);
2265 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2267 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2268 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2269 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2271 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2272 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2273 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2274 SV_FlushBroadcastMessages();
2277 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2279 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2280 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2281 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2282 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2283 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2284 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2285 SV_FlushBroadcastMessages();
2288 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2290 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2291 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2292 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2294 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2295 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2296 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2298 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2299 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2300 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2302 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2303 SV_FlushBroadcastMessages();
2306 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2307 //this function originally written by KrimZon, made shorter by LordHavoc
2308 static void VM_SV_clientcommand(prvm_prog_t *prog)
2310 client_t *temp_client;
2312 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2314 //find client for this entity
2315 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2316 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2318 Con_Print("PF_clientcommand: entity is not a client\n");
2322 temp_client = host_client;
2323 host_client = svs.clients + i;
2324 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
2325 host_client = temp_client;
2328 //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)
2329 static void VM_SV_setattachment(prvm_prog_t *prog)
2331 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2332 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2333 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2336 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2338 if (e == prog->edicts)
2340 VM_Warning(prog, "setattachment: can not modify world entity\n");
2343 if (e->priv.server->free)
2345 VM_Warning(prog, "setattachment: can not modify free entity\n");
2349 if (tagentity == NULL)
2350 tagentity = prog->edicts;
2354 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2356 model = SV_GetModelFromEdict(tagentity);
2359 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2361 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);
2364 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));
2367 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2368 PRVM_serveredictfloat(e, tag_index) = tagindex;
2371 /////////////////////////////////////////
2372 // DP_MD3_TAGINFO extension coded by VorteX
2374 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2378 i = (int)PRVM_serveredictfloat(e, modelindex);
2379 if (i < 1 || i >= MAX_MODELS)
2382 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2385 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2392 Matrix4x4_CreateIdentity(tag_localmatrix);
2394 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2396 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2407 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2410 float pitchsign = 1;
2412 scale = PRVM_serveredictfloat(ent, scale);
2417 Matrix4x4_CreateFromQuakeEntity(out, PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2] + PRVM_serveredictvector(ent, view_ofs)[2], PRVM_serveredictvector(ent, v_angle)[0], PRVM_serveredictvector(ent, v_angle)[1], PRVM_serveredictvector(ent, v_angle)[2], scale * cl_viewmodel_scale.value);
2420 pitchsign = SV_GetPitchSign(prog, ent);
2421 Matrix4x4_CreateFromQuakeEntity(out, PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2], pitchsign * PRVM_serveredictvector(ent, angles)[0], PRVM_serveredictvector(ent, angles)[1], PRVM_serveredictvector(ent, angles)[2], scale);
2425 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2428 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2430 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2431 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2432 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2433 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2435 *out = identitymatrix;
2439 // Warnings/errors code:
2440 // 0 - normal (everything all-right)
2443 // 3 - null or non-precached model
2444 // 4 - no tags with requested index
2445 // 5 - runaway loop at attachment chain
2446 extern cvar_t cl_bob;
2447 extern cvar_t cl_bobcycle;
2448 extern cvar_t cl_bobup;
2449 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2452 int modelindex, attachloop;
2453 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2456 *out = identitymatrix; // warnings and errors return identical matrix
2458 if (ent == prog->edicts)
2460 if (ent->priv.server->free)
2463 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2464 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2467 model = SV_GetModelByIndex(modelindex);
2469 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2470 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2471 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2473 tagmatrix = identitymatrix;
2474 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2478 if (attachloop >= 256) // prevent runaway looping
2480 // apply transformation by child's tagindex on parent entity and then
2481 // by parent entity itself
2482 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2483 if (ret && attachloop == 0)
2485 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2486 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2487 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2488 // next iteration we process the parent entity
2489 if (PRVM_serveredictedict(ent, tag_entity))
2491 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2492 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2499 // RENDER_VIEWMODEL magic
2500 if (PRVM_serveredictedict(ent, viewmodelforclient))
2502 Matrix4x4_Copy(&tagmatrix, out);
2503 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2505 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2506 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2509 // Cl_bob, ported from rendering code
2510 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2513 // LordHavoc: this code is *weird*, but not replacable (I think it
2514 // should be done in QC on the server, but oh well, quake is quake)
2515 // LordHavoc: figured out bobup: the time at which the sin is at 180
2516 // degrees (which allows lengthening or squishing the peak or valley)
2517 cycle = sv.time/cl_bobcycle.value;
2518 cycle -= (int)cycle;
2519 if (cycle < cl_bobup.value)
2520 cycle = sin(M_PI * cycle / cl_bobup.value);
2522 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2523 // bob is proportional to velocity in the xy plane
2524 // (don't count Z, or jumping messes it up)
2525 bob = sqrt(PRVM_serveredictvector(ent, velocity)[0]*PRVM_serveredictvector(ent, velocity)[0] + PRVM_serveredictvector(ent, velocity)[1]*PRVM_serveredictvector(ent, velocity)[1])*cl_bob.value;
2526 bob = bob*0.3 + bob*0.7*cycle;
2527 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2534 //float(entity ent, string tagname) gettagindex;
2536 static void VM_SV_gettagindex(prvm_prog_t *prog)
2539 const char *tag_name;
2542 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2544 ent = PRVM_G_EDICT(OFS_PARM0);
2545 tag_name = PRVM_G_STRING(OFS_PARM1);
2547 if (ent == prog->edicts)
2549 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2552 if (ent->priv.server->free)
2554 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2559 if (!SV_GetModelFromEdict(ent))
2560 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2563 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2565 if(developer_extra.integer)
2566 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2568 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2571 //vector(entity ent, float tagindex) gettaginfo;
2572 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2576 matrix4x4_t tag_matrix;
2577 matrix4x4_t tag_localmatrix;
2579 const char *tagname;
2581 vec3_t fo, le, up, trans;
2582 const dp_model_t *model;
2584 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2586 e = PRVM_G_EDICT(OFS_PARM0);
2587 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2589 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2590 Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
2591 VectorScale(le, -1, PRVM_serverglobalvector(v_right));
2592 model = SV_GetModelFromEdict(e);
2593 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2594 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
2595 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2596 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2597 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2599 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2600 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2601 VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
2602 VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
2603 VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
2604 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2609 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2612 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2615 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2618 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2621 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2626 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2627 static void VM_SV_dropclient(prvm_prog_t *prog)
2630 client_t *oldhostclient;
2631 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2632 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2633 if (clientnum < 0 || clientnum >= svs.maxclients)
2635 VM_Warning(prog, "dropclient: not a client\n");
2638 if (!svs.clients[clientnum].active)
2640 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2643 oldhostclient = host_client;
2644 host_client = svs.clients + clientnum;
2645 SV_DropClient(false);
2646 host_client = oldhostclient;
2649 //entity() spawnclient (DP_SV_BOTCLIENT)
2650 static void VM_SV_spawnclient(prvm_prog_t *prog)
2654 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2655 prog->xfunction->builtinsprofile += 2;
2657 for (i = 0;i < svs.maxclients;i++)
2659 if (!svs.clients[i].active)
2661 prog->xfunction->builtinsprofile += 100;
2662 SV_ConnectClient (i, NULL);
2663 // this has to be set or else ClientDisconnect won't be called
2664 // we assume the qc will call ClientConnect...
2665 svs.clients[i].clientconnectcalled = true;
2666 ed = PRVM_EDICT_NUM(i + 1);
2670 VM_RETURN_EDICT(ed);
2673 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2674 static void VM_SV_clienttype(prvm_prog_t *prog)
2677 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2678 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2679 if (clientnum < 0 || clientnum >= svs.maxclients)
2680 PRVM_G_FLOAT(OFS_RETURN) = 3;
2681 else if (!svs.clients[clientnum].active)
2682 PRVM_G_FLOAT(OFS_RETURN) = 0;
2683 else if (svs.clients[clientnum].netconnection)
2684 PRVM_G_FLOAT(OFS_RETURN) = 1;
2686 PRVM_G_FLOAT(OFS_RETURN) = 2;
2693 string(string key) serverkey
2696 static void VM_SV_serverkey(prvm_prog_t *prog)
2698 char string[VM_STRINGTEMP_LENGTH];
2699 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2700 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2701 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2704 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2705 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2710 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2712 e = PRVM_G_EDICT(OFS_PARM0);
2713 if (e == prog->edicts)
2715 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2718 if (e->priv.server->free)
2720 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2723 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2724 if (i <= 0 || i >= MAX_MODELS)
2726 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2729 if (!sv.model_precache[i][0])
2731 VM_Warning(prog, "setmodelindex: model not precached\n");
2735 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2736 PRVM_serveredictfloat(e, modelindex) = i;
2738 mod = SV_GetModelByIndex(i);
2742 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2743 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2745 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2748 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2751 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2752 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2755 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2757 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2759 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2760 if (i <= 0 || i >= MAX_MODELS)
2762 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2765 if (!sv.model_precache[i][0])
2767 VM_Warning(prog, "modelnameforindex: model not precached\n");
2771 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2774 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2775 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2778 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2779 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2782 PRVM_G_FLOAT(OFS_RETURN) = i;
2785 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2786 static void VM_SV_trailparticles(prvm_prog_t *prog)
2788 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2790 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2793 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2794 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2795 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2796 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2797 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2798 SV_FlushBroadcastMessages();
2801 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2802 static void VM_SV_pointparticles(prvm_prog_t *prog)
2804 int effectnum, count;
2806 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2808 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2811 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2812 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2813 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2814 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2815 if (count == 1 && !VectorLength2(vel))
2818 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2819 MSG_WriteShort(&sv.datagram, effectnum);
2820 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2824 // 1+2+12+12+2=29 bytes
2825 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2826 MSG_WriteShort(&sv.datagram, effectnum);
2827 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2828 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2829 MSG_WriteShort(&sv.datagram, count);
2832 SV_FlushBroadcastMessages();
2835 //PF_setpause, // void(float pause) setpause = #531;
2836 static void VM_SV_setpause(prvm_prog_t *prog) {
2838 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2839 if (pauseValue != 0) { //pause the game
2841 sv.pausedstart = realtime;
2842 } else { //disable pause, in case it was enabled
2843 if (sv.paused != 0) {
2848 // send notification to all clients
2849 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2850 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2853 // #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.
2854 static void VM_SV_skel_create(prvm_prog_t *prog)
2856 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2857 dp_model_t *model = SV_GetModelByIndex(modelindex);
2858 skeleton_t *skeleton;
2860 PRVM_G_FLOAT(OFS_RETURN) = 0;
2861 if (!model || !model->num_bones)
2863 for (i = 0;i < MAX_EDICTS;i++)
2864 if (!prog->skeletons[i])
2866 if (i == MAX_EDICTS)
2868 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2869 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2870 skeleton->model = model;
2871 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2872 // initialize to identity matrices
2873 for (i = 0;i < skeleton->model->num_bones;i++)
2874 skeleton->relativetransforms[i] = identitymatrix;
2877 // #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
2878 static void VM_SV_skel_build(prvm_prog_t *prog)
2880 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2881 skeleton_t *skeleton;
2882 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2883 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2884 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2885 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2886 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2887 dp_model_t *model = SV_GetModelByIndex(modelindex);
2892 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2893 frameblend_t frameblend[MAX_FRAMEBLENDS];
2894 matrix4x4_t blendedmatrix;
2896 PRVM_G_FLOAT(OFS_RETURN) = 0;
2897 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2899 firstbone = max(0, firstbone);
2900 lastbone = min(lastbone, model->num_bones - 1);
2901 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2902 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2903 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
2904 blendfrac = 1.0f - retainfrac;
2905 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2906 frameblend[numblends].lerp *= blendfrac;
2907 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2909 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2910 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2911 for (blendindex = 0;blendindex < numblends;blendindex++)
2913 Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2914 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2916 skeleton->relativetransforms[bonenum] = blendedmatrix;
2918 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2921 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2922 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
2924 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2925 skeleton_t *skeleton;
2926 PRVM_G_FLOAT(OFS_RETURN) = 0;
2927 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2929 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2932 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2933 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
2935 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2936 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2937 skeleton_t *skeleton;
2938 PRVM_G_INT(OFS_RETURN) = 0;
2939 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2941 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2943 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
2946 // #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)
2947 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
2949 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2950 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2951 skeleton_t *skeleton;
2952 PRVM_G_FLOAT(OFS_RETURN) = 0;
2953 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2955 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2957 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2960 // #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
2961 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
2963 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2964 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2965 skeleton_t *skeleton;
2966 PRVM_G_FLOAT(OFS_RETURN) = 0;
2967 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2969 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2972 // #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)
2973 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
2975 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2976 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2977 skeleton_t *skeleton;
2979 vec3_t forward, left, up, origin;
2980 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2981 VectorClear(PRVM_clientglobalvector(v_forward));
2982 VectorClear(PRVM_clientglobalvector(v_right));
2983 VectorClear(PRVM_clientglobalvector(v_up));
2984 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2986 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2988 matrix = skeleton->relativetransforms[bonenum];
2989 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2990 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2991 VectorNegate(left, PRVM_clientglobalvector(v_right));
2992 VectorCopy(up, PRVM_clientglobalvector(v_up));
2993 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2996 // #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)
2997 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
2999 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3000 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3001 skeleton_t *skeleton;
3004 vec3_t forward, left, up, origin;
3005 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3006 VectorClear(PRVM_clientglobalvector(v_forward));
3007 VectorClear(PRVM_clientglobalvector(v_right));
3008 VectorClear(PRVM_clientglobalvector(v_up));
3009 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3011 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3013 matrix = skeleton->relativetransforms[bonenum];
3014 // convert to absolute
3015 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3018 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3020 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3021 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3022 VectorNegate(left, PRVM_clientglobalvector(v_right));
3023 VectorCopy(up, PRVM_clientglobalvector(v_up));
3024 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3027 // #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)
3028 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3030 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3031 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3032 vec3_t forward, left, up, origin;
3033 skeleton_t *skeleton;
3035 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3037 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3039 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3040 VectorNegate(PRVM_clientglobalvector(v_right), left);
3041 VectorCopy(PRVM_clientglobalvector(v_up), up);
3042 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3043 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3044 skeleton->relativetransforms[bonenum] = matrix;
3047 // #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)
3048 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3050 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3051 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3052 vec3_t forward, left, up, origin;
3053 skeleton_t *skeleton;
3056 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3058 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3060 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3061 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3062 VectorNegate(PRVM_clientglobalvector(v_right), left);
3063 VectorCopy(PRVM_clientglobalvector(v_up), up);
3064 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3065 temp = skeleton->relativetransforms[bonenum];
3066 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3069 // #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)
3070 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3072 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3073 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3074 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3076 vec3_t forward, left, up, origin;
3077 skeleton_t *skeleton;
3080 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3082 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3083 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3084 VectorNegate(PRVM_clientglobalvector(v_right), left);
3085 VectorCopy(PRVM_clientglobalvector(v_up), up);
3086 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3087 firstbone = max(0, firstbone);
3088 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3089 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3091 temp = skeleton->relativetransforms[bonenum];
3092 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3096 // #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
3097 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3099 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3100 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3101 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3102 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3104 skeleton_t *skeletondst;
3105 skeleton_t *skeletonsrc;
3106 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3108 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3110 firstbone = max(0, firstbone);
3111 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3112 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3113 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3114 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3117 // #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)
3118 static void VM_SV_skel_delete(prvm_prog_t *prog)
3120 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3121 skeleton_t *skeleton;
3122 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3125 prog->skeletons[skeletonindex] = NULL;
3128 // #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
3129 static void VM_SV_frameforname(prvm_prog_t *prog)
3131 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3132 dp_model_t *model = SV_GetModelByIndex(modelindex);
3133 const char *name = PRVM_G_STRING(OFS_PARM1);
3135 PRVM_G_FLOAT(OFS_RETURN) = -1;
3136 if (!model || !model->animscenes)
3138 for (i = 0;i < model->numframes;i++)
3140 if (!strcasecmp(model->animscenes[i].name, name))
3142 PRVM_G_FLOAT(OFS_RETURN) = i;
3148 // #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.
3149 static void VM_SV_frameduration(prvm_prog_t *prog)
3151 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3152 dp_model_t *model = SV_GetModelByIndex(modelindex);
3153 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3154 PRVM_G_FLOAT(OFS_RETURN) = 0;
3155 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3157 if (model->animscenes[framenum].framerate)
3158 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3162 prvm_builtin_t vm_sv_builtins[] = {
3163 NULL, // #0 NULL function (not callable) (QUAKE)
3164 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3165 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3166 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3167 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3168 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3169 VM_break, // #6 void() break (QUAKE)
3170 VM_random, // #7 float() random (QUAKE)
3171 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3172 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3173 VM_error, // #10 void(string e) error (QUAKE)
3174 VM_objerror, // #11 void(string e) objerror (QUAKE)
3175 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3176 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3177 VM_spawn, // #14 entity() spawn (QUAKE)
3178 VM_remove, // #15 void(entity e) remove (QUAKE)
3179 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3180 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3181 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3182 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3183 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3184 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3185 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3186 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3187 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3188 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3189 VM_ftos, // #26 string(float f) ftos (QUAKE)
3190 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3191 VM_coredump, // #28 void() coredump (QUAKE)
3192 VM_traceon, // #29 void() traceon (QUAKE)
3193 VM_traceoff, // #30 void() traceoff (QUAKE)
3194 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3195 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3196 NULL, // #33 (QUAKE)
3197 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3198 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3199 VM_rint, // #36 float(float v) rint (QUAKE)
3200 VM_floor, // #37 float(float v) floor (QUAKE)
3201 VM_ceil, // #38 float(float v) ceil (QUAKE)
3202 NULL, // #39 (QUAKE)
3203 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3204 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3205 NULL, // #42 (QUAKE)
3206 VM_fabs, // #43 float(float f) fabs (QUAKE)
3207 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3208 VM_cvar, // #45 float(string s) cvar (QUAKE)
3209 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3210 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3211 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3212 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3213 NULL, // #50 (QUAKE)
3214 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3215 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3216 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3217 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3218 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3219 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3220 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3221 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3222 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3223 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3224 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3225 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3226 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3227 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3228 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3229 NULL, // #66 (QUAKE)
3230 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3231 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3232 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3233 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3234 NULL, // #71 (QUAKE)
3235 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3236 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3237 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3238 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3239 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3240 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3241 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3242 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3243 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3244 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3245 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3246 NULL, // #83 (QUAKE)
3247 NULL, // #84 (QUAKE)
3248 NULL, // #85 (QUAKE)
3249 NULL, // #86 (QUAKE)
3250 NULL, // #87 (QUAKE)
3251 NULL, // #88 (QUAKE)
3252 NULL, // #89 (QUAKE)
3253 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3254 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3255 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3256 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3257 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3258 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3259 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3260 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3261 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3262 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3263 // FrikaC and Telejano range #100-#199
3274 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3275 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3276 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3277 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3278 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3279 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3280 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3281 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3282 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3283 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3364 // FTEQW range #200-#299
3383 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3386 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3387 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3388 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3389 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3390 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3391 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3392 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3393 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3394 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3395 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3397 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3405 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3428 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.
3429 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
3430 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3431 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3432 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)
3433 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
3434 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)
3435 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)
3436 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)
3437 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)
3438 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)
3439 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
3440 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)
3441 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
3442 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.
3465 // CSQC range #300-#399
3466 NULL, // #300 void() clearscene (EXT_CSQC)
3467 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3468 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3469 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3470 NULL, // #304 void() renderscene (EXT_CSQC)
3471 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3472 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3473 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3474 NULL, // #308 void() R_EndPolygon
3476 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3477 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3481 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3482 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3483 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3484 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3485 NULL, // #319 void(string name) freepic (EXT_CSQC)
3486 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3487 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3488 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3489 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3490 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3491 NULL, // #325 void(void) drawresetcliparea
3496 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3497 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3498 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3499 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3500 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3501 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3502 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3503 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3504 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3505 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3506 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3507 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3508 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3509 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3510 NULL, // #344 vector() getmousepos (EXT_CSQC)
3511 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3512 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3513 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3514 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3515 NULL, // #349 float() isdemo (EXT_CSQC)
3516 VM_isserver, // #350 float() isserver (EXT_CSQC)
3517 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3518 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3519 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3520 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3526 NULL, // #360 float() readbyte (EXT_CSQC)
3527 NULL, // #361 float() readchar (EXT_CSQC)
3528 NULL, // #362 float() readshort (EXT_CSQC)
3529 NULL, // #363 float() readlong (EXT_CSQC)
3530 NULL, // #364 float() readcoord (EXT_CSQC)
3531 NULL, // #365 float() readangle (EXT_CSQC)
3532 NULL, // #366 string() readstring (EXT_CSQC)
3533 NULL, // #367 float() readfloat (EXT_CSQC)
3566 // LordHavoc's range #400-#499
3567 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3568 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3569 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3570 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3571 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3572 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3573 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3574 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3575 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)
3576 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3577 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3578 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3579 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3580 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3581 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3582 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3583 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3584 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3585 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3586 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3587 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3588 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3589 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3590 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3591 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3592 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3593 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3594 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3595 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3596 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3597 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3598 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3599 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3600 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3601 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3602 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3603 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3604 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3605 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3606 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3607 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3608 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3609 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3610 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3611 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3612 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3613 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3614 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3615 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3616 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3617 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3618 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3619 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3620 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3621 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3622 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3623 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3624 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3626 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3627 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3628 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3629 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3630 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3631 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3632 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3633 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3634 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3635 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3636 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3638 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3639 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3640 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3641 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3642 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3643 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3644 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3645 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3646 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3647 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3648 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3649 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3650 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3651 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3652 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3653 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3661 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3662 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3663 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3664 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3665 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3666 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3667 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3668 VM_SV_WritePicture, // #501
3670 VM_whichpack, // #503 string(string) whichpack = #503;
3677 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3678 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3679 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3680 VM_uri_get, // #513 float(string uri, float id, [string post_contenttype, string post_delim, [float buf]]) uri_get = #513; (DP_QC_URI_GET, DP_QC_URI_POST)
3681 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3682 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3683 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3684 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3685 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3686 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3696 VM_loadfromdata, // #529
3697 VM_loadfromfile, // #530
3698 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3700 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3701 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3707 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3708 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3709 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3772 VM_callfunction, // #605
3773 VM_writetofile, // #606
3774 VM_isfunction, // #607
3780 VM_parseentitydata, // #613
3791 VM_SV_getextresponse, // #624 string getextresponse(void)
3794 VM_sprintf, // #627 string sprintf(string format, ...)
3795 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3796 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3806 VM_digest_hex, // #639
3810 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3812 void SVVM_init_cmd(prvm_prog_t *prog)
3817 void SVVM_reset_cmd(prvm_prog_t *prog)
3819 World_End(&sv.world);
3820 if(PRVM_serverfunction(SV_Shutdown))
3822 func_t s = PRVM_serverfunction(SV_Shutdown);
3823 PRVM_serverglobalfloat(time) = sv.time;
3824 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3825 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");