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_MULTIFRAME_INTERPOLATION "
29 "DP_CSQC_BOXPARTICLES "
30 "DP_CSQC_SPAWNPARTICLE "
31 "DP_CSQC_QUERYRENDERENTITY "
32 "DP_CSQC_ROTATEMOVES "
45 "DP_EF_RESTARTANIM_BIT "
50 "DP_ENT_CUSTOMCOLORMAP "
51 "DP_ENT_EXTERIORMODELTOCLIENT "
54 "DP_ENT_LOWPRECISION "
56 "DP_ENT_TRAILEFFECTNUM "
58 "DP_GFX_EXTERNALTEXTURES "
59 "DP_GFX_EXTERNALTEXTURES_PERMAP "
61 "DP_GFX_MODEL_INTERPOLATION "
62 "DP_GFX_QUAKE3MODELTAGS "
66 "DP_GFX_FONTS_FREETYPE "
68 "DP_FONT_VARIABLEWIDTH "
70 "DP_HALFLIFE_MAP_CVAR "
73 "DP_LIGHTSTYLE_STATICVALUE "
77 "DP_MOVETYPEBOUNCEMISSILE "
78 "DP_MOVETYPEFLYWORLDONLY "
81 "DP_QC_ASINACOSATANATAN2TAN "
87 "DP_QC_CVAR_DEFSTRING "
88 "DP_QC_CVAR_DESCRIPTION "
92 "DP_QC_DIGEST_SHA256 "
97 "DP_QC_EXTRESPONSEPACKET "
99 "DP_QC_FINDCHAINFLAGS "
100 "DP_QC_FINDCHAINFLOAT "
101 "DP_QC_FINDCHAIN_TOFIELD "
107 "DP_QC_GETSURFACETRIANGLE "
108 "DP_QC_GETSURFACEPOINTATTRIBUTE "
110 "DP_QC_GETTAGINFO_BONEPROPERTIES "
112 "DP_QC_GETTIME_CDTRACK "
116 "DP_QC_MULTIPLETEMPSTRINGS "
117 "DP_QC_NUM_FOR_EDICT "
119 "DP_QC_SINCOSSQRTPOW "
122 "DP_QC_STRINGBUFFERS "
123 "DP_QC_STRINGBUFFERS_CVARLIST "
124 "DP_QC_STRINGCOLORFUNCTIONS "
125 "DP_QC_STRING_CASE_FUNCTIONS "
127 "DP_QC_TOKENIZEBYSEPARATOR "
128 "DP_QC_TOKENIZE_CONSOLE "
131 "DP_QC_TRACE_MOVETYPE_HITMODEL "
132 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
133 "DP_QC_UNLIMITEDTEMPSTRINGS "
137 "DP_QC_VECTOANGLES_WITH_ROLL "
138 "DP_QC_VECTORVECTORS "
145 "DP_SKELETONOBJECTS "
146 "DP_SND_DIRECTIONLESSATTNNONE "
148 "DP_SND_SOUND7_WIP1 "
149 "DP_SND_SOUND7_WIP2 "
153 "DP_SND_GETSOUNDTIME "
155 "DP_VIDEO_SUBTITLES "
159 "DP_SV_BOUNCEFACTOR "
160 "DP_SV_CLIENTCAMERA "
161 "DP_SV_CLIENTCOLORS "
164 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
165 "DP_SV_DISCARDABLEDEMO "
166 "DP_SV_DRAWONLYTOCLIENT "
169 "DP_SV_ENTITYCONTENTSTRANSITION "
170 "DP_SV_MODELFLAGS_AS_EFFECTS "
171 "DP_SV_MOVETYPESTEP_LANDEVENT "
173 "DP_SV_NODRAWTOCLIENT "
174 "DP_SV_ONENTITYNOSPAWNFUNCTION "
175 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
177 "DP_SV_PING_PACKETLOSS "
178 "DP_SV_PLAYERPHYSICS "
180 "DP_SV_POINTPARTICLES "
182 "DP_SV_PRECACHEANYTIME "
186 "DP_SV_ROTATINGBMODEL "
190 "DP_SV_SPAWNFUNC_PREFIX "
191 "DP_SV_WRITEPICTURE "
192 "DP_SV_WRITEUNTERMINATEDSTRING "
196 "DP_TE_EXPLOSIONRGB "
198 "DP_TE_PARTICLECUBE "
199 "DP_TE_PARTICLERAIN "
200 "DP_TE_PARTICLESNOW "
202 "DP_TE_QUADEFFECTS1 "
205 "DP_TE_STANDARDEFFECTBUILTINS "
206 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
210 "FTE_CSQC_SKELETONOBJECTS "
213 "KRIMZON_SV_PARSECLIENTCOMMAND "
216 "NEXUIZ_PLAYERMODEL "
218 "PRYDON_CLIENTCURSOR "
219 "TENEBRAE_GFX_DLIGHTS "
222 //"EXT_CSQC " // not ready yet
229 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.
231 setorigin (entity, origin)
234 static void VM_SV_setorigin(prvm_prog_t *prog)
239 VM_SAFEPARMCOUNT(2, VM_setorigin);
241 e = PRVM_G_EDICT(OFS_PARM0);
242 if (e == prog->edicts)
244 VM_Warning(prog, "setorigin: can not modify world entity\n");
247 if (e->priv.server->free)
249 VM_Warning(prog, "setorigin: can not modify free entity\n");
252 org = PRVM_G_VECTOR(OFS_PARM1);
253 VectorCopy (org, PRVM_serveredictvector(e, origin));
254 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
255 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
259 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
260 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qboolean rotate)
264 for (i=0 ; i<3 ; i++)
266 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
268 // set derived values
269 VectorCopy (min, PRVM_serveredictvector(e, mins));
270 VectorCopy (max, PRVM_serveredictvector(e, maxs));
271 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
280 the size box is rotated by the current angle
281 LordHavoc: no it isn't...
283 setsize (entity, minvector, maxvector)
286 static void VM_SV_setsize(prvm_prog_t *prog)
291 VM_SAFEPARMCOUNT(3, VM_setsize);
293 e = PRVM_G_EDICT(OFS_PARM0);
294 if (e == prog->edicts)
296 VM_Warning(prog, "setsize: can not modify world entity\n");
299 if (e->priv.server->free)
301 VM_Warning(prog, "setsize: can not modify free entity\n");
304 min = PRVM_G_VECTOR(OFS_PARM1);
305 max = PRVM_G_VECTOR(OFS_PARM2);
306 SetMinMaxSize(prog, e, min, max, false);
314 setmodel(entity, model)
317 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
318 static void VM_SV_setmodel(prvm_prog_t *prog)
324 VM_SAFEPARMCOUNT(2, VM_setmodel);
326 e = PRVM_G_EDICT(OFS_PARM0);
327 if (e == prog->edicts)
329 VM_Warning(prog, "setmodel: can not modify world entity\n");
332 if (e->priv.server->free)
334 VM_Warning(prog, "setmodel: can not modify free entity\n");
337 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
338 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
339 PRVM_serveredictfloat(e, modelindex) = i;
341 mod = SV_GetModelByIndex(i);
345 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
346 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
348 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
351 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
358 single print to a specific client
360 sprint(clientent, value)
363 static void VM_SV_sprint(prvm_prog_t *prog)
367 char string[VM_STRINGTEMP_LENGTH];
369 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
371 VM_VarString(prog, 1, string, sizeof(string));
373 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
374 // LordHavoc: div0 requested that sprintto world operate like print
381 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
383 VM_Warning(prog, "tried to centerprint to a non-client\n");
387 client = svs.clients + entnum-1;
388 if (!client->netconnection)
391 MSG_WriteChar(&client->netconnection->message,svc_print);
392 MSG_WriteString(&client->netconnection->message, string);
400 single print to a specific client
402 centerprint(clientent, value)
405 static void VM_SV_centerprint(prvm_prog_t *prog)
409 char string[VM_STRINGTEMP_LENGTH];
411 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
413 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
415 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
417 VM_Warning(prog, "tried to centerprint to a non-client\n");
421 client = svs.clients + entnum-1;
422 if (!client->netconnection)
425 VM_VarString(prog, 1, string, sizeof(string));
426 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
427 MSG_WriteString(&client->netconnection->message, string);
434 particle(origin, color, count)
437 static void VM_SV_particle(prvm_prog_t *prog)
443 VM_SAFEPARMCOUNT(4, VM_SV_particle);
445 org = PRVM_G_VECTOR(OFS_PARM0);
446 dir = PRVM_G_VECTOR(OFS_PARM1);
447 color = PRVM_G_FLOAT(OFS_PARM2);
448 count = PRVM_G_FLOAT(OFS_PARM3);
449 SV_StartParticle (org, dir, (int)color, (int)count);
459 static void VM_SV_ambientsound(prvm_prog_t *prog)
463 float vol, attenuation;
466 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
468 pos = PRVM_G_VECTOR (OFS_PARM0);
469 samp = PRVM_G_STRING(OFS_PARM1);
470 vol = PRVM_G_FLOAT(OFS_PARM2);
471 attenuation = PRVM_G_FLOAT(OFS_PARM3);
473 // check to see if samp was properly precached
474 soundnum = SV_SoundIndex(samp, 1);
482 // add an svc_spawnambient command to the level signon packet
485 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
487 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
489 MSG_WriteVector(&sv.signon, pos, sv.protocol);
491 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
492 MSG_WriteShort (&sv.signon, soundnum);
494 MSG_WriteByte (&sv.signon, soundnum);
496 MSG_WriteByte (&sv.signon, (int)(vol*255));
497 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
505 Each entity can have eight independant sound sources, like voice,
508 Channel 0 is an auto-allocate channel, the others override anything
509 already running on that entity/channel pair.
511 An attenuation of 0 will play full volume everywhere in the level.
512 Larger attenuations will drop off.
516 static void VM_SV_sound(prvm_prog_t *prog)
520 prvm_edict_t *entity;
526 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
528 entity = PRVM_G_EDICT(OFS_PARM0);
529 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
530 sample = PRVM_G_STRING(OFS_PARM2);
531 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
534 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
538 attenuation = PRVM_G_FLOAT(OFS_PARM4);
542 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
547 if(channel >= 8 && channel <= 15) // weird QW feature
549 flags |= CHANFLAG_RELIABLE;
554 flags = PRVM_G_FLOAT(OFS_PARM6);
556 if (volume < 0 || volume > 255)
558 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
562 if (attenuation < 0 || attenuation > 4)
564 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
568 channel = CHAN_USER2ENGINE(channel);
570 if (!IS_CHAN(channel))
572 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
576 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE, pitchchange);
583 Follows the same logic as VM_SV_sound, except instead of
584 an entity, an origin for the sound is provided, and channel
585 is omitted (since no entity is being tracked).
589 static void VM_SV_pointsound(prvm_prog_t *prog)
597 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
599 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
600 sample = PRVM_G_STRING(OFS_PARM1);
601 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
602 attenuation = PRVM_G_FLOAT(OFS_PARM3);
603 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
605 if (volume < 0 || volume > 255)
607 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
611 if (attenuation < 0 || attenuation > 4)
613 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
617 SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
624 Used for use tracing and shot targeting
625 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
626 if the tryents flag is set.
628 traceline (vector1, vector2, movetype, ignore)
631 static void VM_SV_traceline(prvm_prog_t *prog)
638 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
640 prog->xfunction->builtinsprofile += 30;
642 v1 = PRVM_G_VECTOR(OFS_PARM0);
643 v2 = PRVM_G_VECTOR(OFS_PARM1);
644 move = (int)PRVM_G_FLOAT(OFS_PARM2);
645 ent = PRVM_G_EDICT(OFS_PARM3);
647 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]))
648 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));
650 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
652 VM_SetTraceGlobals(prog, &trace);
660 Used for use tracing and shot targeting
661 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
662 if the tryents flag is set.
664 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
667 // LordHavoc: added this for my own use, VERY useful, similar to traceline
668 static void VM_SV_tracebox(prvm_prog_t *prog)
670 float *v1, *v2, *m1, *m2;
675 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
677 prog->xfunction->builtinsprofile += 30;
679 v1 = PRVM_G_VECTOR(OFS_PARM0);
680 m1 = PRVM_G_VECTOR(OFS_PARM1);
681 m2 = PRVM_G_VECTOR(OFS_PARM2);
682 v2 = PRVM_G_VECTOR(OFS_PARM3);
683 move = (int)PRVM_G_FLOAT(OFS_PARM4);
684 ent = PRVM_G_EDICT(OFS_PARM5);
686 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]))
687 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));
689 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
691 VM_SetTraceGlobals(prog, &trace);
694 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
699 vec3_t original_origin;
700 vec3_t original_velocity;
701 vec3_t original_angles;
702 vec3_t original_avelocity;
705 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
706 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
707 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
708 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
710 gravity = PRVM_serveredictfloat(tossent, gravity);
713 gravity *= sv_gravity.value * 0.025;
715 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
717 SV_CheckVelocity (tossent);
718 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
719 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
720 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
721 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
722 trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
723 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
724 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
726 if (trace.fraction < 1)
730 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
731 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
732 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
733 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
738 static void VM_SV_tracetoss(prvm_prog_t *prog)
742 prvm_edict_t *ignore;
744 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
746 prog->xfunction->builtinsprofile += 600;
748 ent = PRVM_G_EDICT(OFS_PARM0);
749 if (ent == prog->edicts)
751 VM_Warning(prog, "tracetoss: can not use world entity\n");
754 ignore = PRVM_G_EDICT(OFS_PARM1);
756 trace = SV_Trace_Toss(prog, ent, ignore);
758 VM_SetTraceGlobals(prog, &trace);
761 //============================================================================
763 static int checkpvsbytes;
764 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
766 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
772 // cycle to the next one
774 check = bound(1, check, svs.maxclients);
775 if (check == svs.maxclients)
783 prog->xfunction->builtinsprofile++;
785 if (i == svs.maxclients+1)
787 // look up the client's edict
788 ent = PRVM_EDICT_NUM(i);
789 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
790 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
792 // found a valid client (possibly the same one again)
796 // get the PVS for the entity
797 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
799 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
800 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
809 Returns a client (or object that has a client enemy) that would be a
812 If there is more than one valid option, they are cycled each frame
814 If (self.origin + self.viewofs) is not in the PVS of the current target,
815 it is not returned at all.
820 int c_invis, c_notvis;
821 static void VM_SV_checkclient(prvm_prog_t *prog)
823 prvm_edict_t *ent, *self;
826 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
828 // find a new check if on a new frame
829 if (sv.time - sv.lastchecktime >= 0.1)
831 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
832 sv.lastchecktime = sv.time;
835 // return check if it might be visible
836 ent = PRVM_EDICT_NUM(sv.lastcheck);
837 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
839 VM_RETURN_EDICT(prog->edicts);
843 // if current entity can't possibly see the check entity, return 0
844 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
845 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
846 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
849 VM_RETURN_EDICT(prog->edicts);
853 // might be able to see it
855 VM_RETURN_EDICT(ent);
858 //============================================================================
864 Checks if an entity is in a point's PVS.
865 Should be fast but can be inexact.
867 float checkpvs(vector viewpos, entity viewee) = #240;
870 static void VM_SV_checkpvs(prvm_prog_t *prog)
873 prvm_edict_t *viewee;
878 unsigned char fatpvs[MAX_MAP_LEAFS/8];
881 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
882 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
883 viewee = PRVM_G_EDICT(OFS_PARM1);
885 if(viewee->priv.server->free)
887 VM_Warning(prog, "checkpvs: can not check free entity\n");
888 PRVM_G_FLOAT(OFS_RETURN) = 4;
893 if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
895 // no PVS support on this worldmodel... darn
896 PRVM_G_FLOAT(OFS_RETURN) = 3;
899 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
902 // viewpos isn't in any PVS... darn
903 PRVM_G_FLOAT(OFS_RETURN) = 2;
906 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
908 // using fat PVS like FTEQW does (slow)
909 if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
911 // no PVS support on this worldmodel... darn
912 PRVM_G_FLOAT(OFS_RETURN) = 3;
915 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
918 // viewpos isn't in any PVS... darn
919 PRVM_G_FLOAT(OFS_RETURN) = 2;
922 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax));
931 Sends text over to the client's execution buffer
933 stuffcmd (clientent, value, ...)
936 static void VM_SV_stuffcmd(prvm_prog_t *prog)
940 char string[VM_STRINGTEMP_LENGTH];
942 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
944 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
945 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
947 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
951 VM_VarString(prog, 1, string, sizeof(string));
954 host_client = svs.clients + entnum-1;
955 Host_ClientCommands ("%s", string);
963 Returns a chain of entities that have origins within a spherical area
965 findradius (origin, radius)
968 static void VM_SV_findradius(prvm_prog_t *prog)
970 prvm_edict_t *ent, *chain;
971 vec_t radius, radius2;
972 vec3_t org, eorg, mins, maxs;
975 static prvm_edict_t *touchedicts[MAX_EDICTS];
978 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
981 chainfield = PRVM_G_INT(OFS_PARM2);
983 chainfield = prog->fieldoffsets.chain;
985 prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
987 chain = (prvm_edict_t *)prog->edicts;
989 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
990 radius = PRVM_G_FLOAT(OFS_PARM1);
991 radius2 = radius * radius;
993 mins[0] = org[0] - (radius + 1);
994 mins[1] = org[1] - (radius + 1);
995 mins[2] = org[2] - (radius + 1);
996 maxs[0] = org[0] + (radius + 1);
997 maxs[1] = org[1] + (radius + 1);
998 maxs[2] = org[2] + (radius + 1);
999 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1000 if (numtouchedicts > MAX_EDICTS)
1002 // this never happens
1003 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1004 numtouchedicts = MAX_EDICTS;
1006 for (i = 0;i < numtouchedicts;i++)
1008 ent = touchedicts[i];
1009 prog->xfunction->builtinsprofile++;
1010 // Quake did not return non-solid entities but darkplaces does
1011 // (note: this is the reason you can't blow up fallen zombies)
1012 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1014 // LordHavoc: compare against bounding box rather than center so it
1015 // doesn't miss large objects, and use DotProduct instead of Length
1016 // for a major speedup
1017 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1018 if (sv_gameplayfix_findradiusdistancetobox.integer)
1020 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1021 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1022 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1025 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1026 if (DotProduct(eorg, eorg) < radius2)
1028 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1033 VM_RETURN_EDICT(chain);
1036 static void VM_SV_precache_sound(prvm_prog_t *prog)
1038 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1039 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1042 static void VM_SV_precache_model(prvm_prog_t *prog)
1044 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1045 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1046 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1053 float(float yaw, float dist[, settrace]) walkmove
1056 static void VM_SV_walkmove(prvm_prog_t *prog)
1065 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1067 // assume failure if it returns early
1068 PRVM_G_FLOAT(OFS_RETURN) = 0;
1070 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1071 if (ent == prog->edicts)
1073 VM_Warning(prog, "walkmove: can not modify world entity\n");
1076 if (ent->priv.server->free)
1078 VM_Warning(prog, "walkmove: can not modify free entity\n");
1081 yaw = PRVM_G_FLOAT(OFS_PARM0);
1082 dist = PRVM_G_FLOAT(OFS_PARM1);
1083 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1085 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1088 yaw = yaw*M_PI*2 / 360;
1090 move[0] = cos(yaw)*dist;
1091 move[1] = sin(yaw)*dist;
1094 // save program state, because SV_movestep may call other progs
1095 oldf = prog->xfunction;
1096 oldself = PRVM_serverglobaledict(self);
1098 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1101 // restore program state
1102 prog->xfunction = oldf;
1103 PRVM_serverglobaledict(self) = oldself;
1114 static void VM_SV_droptofloor(prvm_prog_t *prog)
1120 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1122 // assume failure if it returns early
1123 PRVM_G_FLOAT(OFS_RETURN) = 0;
1125 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1126 if (ent == prog->edicts)
1128 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1131 if (ent->priv.server->free)
1133 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1137 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1140 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1141 if (sv_gameplayfix_unstickentities.integer)
1142 SV_UnstickEntity(ent);
1144 trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1145 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1148 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]);
1149 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1150 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1151 VectorSubtract(trace.endpos, offset, trace.endpos);
1152 if (trace.startsolid)
1154 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]);
1155 if (sv_gameplayfix_unstickentities.integer)
1156 SV_UnstickEntity(ent);
1158 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1159 PRVM_serveredictedict(ent, groundentity) = 0;
1160 PRVM_G_FLOAT(OFS_RETURN) = 1;
1162 else if (trace.fraction < 1)
1164 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]);
1165 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1166 if (sv_gameplayfix_unstickentities.integer)
1167 SV_UnstickEntity(ent);
1169 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1170 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1171 PRVM_G_FLOAT(OFS_RETURN) = 1;
1172 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1173 ent->priv.server->suspendedinairflag = true;
1178 if (trace.fraction != 1)
1180 if (trace.fraction < 1)
1181 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1183 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1184 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1185 PRVM_G_FLOAT(OFS_RETURN) = 1;
1186 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1187 ent->priv.server->suspendedinairflag = true;
1196 void(float style, string value) lightstyle
1199 static void VM_SV_lightstyle(prvm_prog_t *prog)
1206 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1208 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1209 val = PRVM_G_STRING(OFS_PARM1);
1211 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1212 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1215 // change the string in sv
1216 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1218 // send message to all clients on this server
1219 if (sv.state != ss_active)
1222 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1224 if (client->active && client->netconnection)
1226 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1227 MSG_WriteChar (&client->netconnection->message,style);
1228 MSG_WriteString (&client->netconnection->message, val);
1238 static void VM_SV_checkbottom(prvm_prog_t *prog)
1240 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1241 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1249 static void VM_SV_pointcontents(prvm_prog_t *prog)
1251 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1252 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1259 Pick a vector for the player to shoot along
1260 vector aim(entity, missilespeed)
1263 static void VM_SV_aim(prvm_prog_t *prog)
1265 prvm_edict_t *ent, *check, *bestent;
1266 vec3_t start, dir, end, bestdir;
1269 float dist, bestdist;
1272 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1274 // assume failure if it returns early
1275 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1276 // if sv_aim is so high it can't possibly accept anything, skip out early
1277 if (sv_aim.value >= 1)
1280 ent = PRVM_G_EDICT(OFS_PARM0);
1281 if (ent == prog->edicts)
1283 VM_Warning(prog, "aim: can not use world entity\n");
1286 if (ent->priv.server->free)
1288 VM_Warning(prog, "aim: can not use free entity\n");
1291 //speed = PRVM_G_FLOAT(OFS_PARM1);
1293 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1296 // try sending a trace straight
1297 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1298 VectorMA (start, 2048, dir, end);
1299 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1300 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1301 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1303 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1308 // try all possible entities
1309 VectorCopy (dir, bestdir);
1310 bestdist = sv_aim.value;
1313 check = PRVM_NEXT_EDICT(prog->edicts);
1314 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1316 prog->xfunction->builtinsprofile++;
1317 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1321 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1322 continue; // don't aim at teammate
1323 for (j=0 ; j<3 ; j++)
1324 end[j] = PRVM_serveredictvector(check, origin)[j]
1325 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1326 VectorSubtract (end, start, dir);
1327 VectorNormalize (dir);
1328 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1329 if (dist < bestdist)
1330 continue; // to far to turn
1331 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1332 if (tr.ent == check)
1333 { // can shoot at this one
1341 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1342 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1343 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1345 VectorNormalize (end);
1346 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1350 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1355 ===============================================================================
1359 ===============================================================================
1362 #define MSG_BROADCAST 0 // unreliable to all
1363 #define MSG_ONE 1 // reliable to one (msg_entity)
1364 #define MSG_ALL 2 // reliable to all
1365 #define MSG_INIT 3 // write to the init string
1366 #define MSG_ENTITY 5
1368 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1374 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1378 return &sv.datagram;
1381 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1382 entnum = PRVM_NUM_FOR_EDICT(ent);
1383 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1385 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1386 return &sv.reliable_datagram;
1389 return &svs.clients[entnum-1].netconnection->message;
1392 VM_Warning(prog, "WriteDest: bad destination\n");
1394 return &sv.reliable_datagram;
1400 return sv.writeentitiestoclient_msg;
1406 static void VM_SV_WriteByte(prvm_prog_t *prog)
1408 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1409 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1412 static void VM_SV_WriteChar(prvm_prog_t *prog)
1414 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1415 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1418 static void VM_SV_WriteShort(prvm_prog_t *prog)
1420 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1421 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1424 static void VM_SV_WriteLong(prvm_prog_t *prog)
1426 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1427 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1430 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1432 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1433 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1436 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1438 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1439 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1442 static void VM_SV_WriteString(prvm_prog_t *prog)
1444 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1445 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1448 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1450 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1451 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1455 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1457 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1458 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1461 // writes a picture as at most size bytes of data
1463 // IMGNAME \0 SIZE(short) IMGDATA
1464 // if failed to read/compress:
1466 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1467 static void VM_SV_WritePicture(prvm_prog_t *prog)
1469 const char *imgname;
1473 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1475 imgname = PRVM_G_STRING(OFS_PARM1);
1476 size = (int) PRVM_G_FLOAT(OFS_PARM2);
1480 MSG_WriteString(WriteDest(prog), imgname);
1481 if(Image_Compress(imgname, size, &buf, &size))
1484 MSG_WriteShort(WriteDest(prog), size);
1485 SZ_Write(WriteDest(prog), (unsigned char *) buf, size);
1490 MSG_WriteShort(WriteDest(prog), 0);
1494 //////////////////////////////////////////////////////////
1496 static void VM_SV_makestatic(prvm_prog_t *prog)
1501 // allow 0 parameters due to an id1 qc bug in which this function is used
1502 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1503 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1505 if (prog->argc >= 1)
1506 ent = PRVM_G_EDICT(OFS_PARM0);
1508 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1509 if (ent == prog->edicts)
1511 VM_Warning(prog, "makestatic: can not modify world entity\n");
1514 if (ent->priv.server->free)
1516 VM_Warning(prog, "makestatic: can not modify free entity\n");
1521 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1526 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1527 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1528 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1530 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1532 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1533 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1534 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1538 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1539 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1540 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1543 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1544 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1545 for (i=0 ; i<3 ; i++)
1547 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1548 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1551 // throw the entity away now
1552 PRVM_ED_Free(prog, ent);
1555 //=============================================================================
1562 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1568 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1570 ent = PRVM_G_EDICT(OFS_PARM0);
1571 i = PRVM_NUM_FOR_EDICT(ent);
1572 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1574 Con_Print("tried to setspawnparms on a non-client\n");
1578 // copy spawn parms out of the client_t
1579 client = svs.clients + i-1;
1580 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1581 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1588 Returns a color vector indicating the lighting at the requested point.
1590 (Internal Operation note: actually measures the light beneath the point, just like
1591 the model lighting on the client)
1596 static void VM_SV_getlight(prvm_prog_t *prog)
1598 vec3_t ambientcolor, diffusecolor, diffusenormal;
1600 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1601 p = PRVM_G_VECTOR(OFS_PARM0);
1602 VectorClear(ambientcolor);
1603 VectorClear(diffusecolor);
1604 VectorClear(diffusenormal);
1605 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1606 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1607 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1612 unsigned char type; // 1/2/8 or other value if isn't used
1616 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1617 static int vm_customstats_last;
1619 void VM_CustomStats_Clear (void)
1623 Z_Free(vm_customstats);
1624 vm_customstats = NULL;
1625 vm_customstats_last = -1;
1629 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1631 prvm_prog_t *prog = SVVM_prog;
1638 for(i=0; i<vm_customstats_last+1 ;i++)
1640 if(!vm_customstats[i].type)
1642 switch(vm_customstats[i].type)
1644 //string as 16 bytes
1647 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1648 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1649 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1650 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1651 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1653 //float field sent as-is
1655 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1657 //integer value of float field
1659 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1667 // void(float index, float type, .void field) SV_AddStat = #232;
1668 // Set up an auto-sent player stat.
1669 // Client's get thier own fields sent to them. Index may not be less than 32.
1670 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1671 // 1: string (4 stats carrying a total of 16 charactures)
1672 // 2: float (one stat, float converted to an integer for transportation)
1673 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1674 static void VM_SV_AddStat(prvm_prog_t *prog)
1679 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1683 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1686 VM_Warning(prog, "PF_SV_AddStat: not enough memory\n");
1690 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1691 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1692 off = PRVM_G_INT (OFS_PARM2);
1697 VM_Warning(prog, "PF_SV_AddStat: index may not be less than 32\n");
1700 if(i >= (MAX_CL_STATS-32))
1702 VM_Warning(prog, "PF_SV_AddStat: index >= MAX_CL_STATS\n");
1705 if(i > (MAX_CL_STATS-32-4) && type == 1)
1707 VM_Warning(prog, "PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1710 vm_customstats[i].type = type;
1711 vm_customstats[i].fieldoffset = off;
1712 if(vm_customstats_last < i)
1713 vm_customstats_last = i;
1720 copies data from one entity to another
1722 copyentity(src, dst)
1725 static void VM_SV_copyentity(prvm_prog_t *prog)
1727 prvm_edict_t *in, *out;
1728 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1729 in = PRVM_G_EDICT(OFS_PARM0);
1730 if (in == prog->edicts)
1732 VM_Warning(prog, "copyentity: can not read world entity\n");
1735 if (in->priv.server->free)
1737 VM_Warning(prog, "copyentity: can not read free entity\n");
1740 out = PRVM_G_EDICT(OFS_PARM1);
1741 if (out == prog->edicts)
1743 VM_Warning(prog, "copyentity: can not modify world entity\n");
1746 if (out->priv.server->free)
1748 VM_Warning(prog, "copyentity: can not modify free entity\n");
1751 memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
1760 sets the color of a client and broadcasts the update to all connected clients
1762 setcolor(clientent, value)
1765 static void VM_SV_setcolor(prvm_prog_t *prog)
1770 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1771 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1772 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1774 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1776 Con_Print("tried to setcolor a non-client\n");
1780 client = svs.clients + entnum-1;
1783 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1784 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1787 if (client->old_colors != client->colors)
1789 client->old_colors = client->colors;
1790 // send notification to all clients
1791 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1792 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1793 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1801 effect(origin, modelname, startframe, framecount, framerate)
1804 static void VM_SV_effect(prvm_prog_t *prog)
1808 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1809 s = PRVM_G_STRING(OFS_PARM1);
1812 VM_Warning(prog, "effect: no model specified\n");
1816 i = SV_ModelIndex(s, 1);
1819 VM_Warning(prog, "effect: model not precached\n");
1823 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1825 VM_Warning(prog, "effect: framecount < 1\n");
1829 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1831 VM_Warning(prog, "effect: framerate < 1\n");
1835 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));
1838 static void VM_SV_te_blood(prvm_prog_t *prog)
1840 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1841 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1843 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1844 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1847 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1848 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1850 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1851 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1852 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1854 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1855 SV_FlushBroadcastMessages();
1858 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1860 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1861 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1863 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1864 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1866 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1868 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1870 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1874 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1876 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1877 SV_FlushBroadcastMessages();
1880 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1882 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1883 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1884 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1886 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1887 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1888 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1890 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1891 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1892 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1893 SV_FlushBroadcastMessages();
1896 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1898 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1899 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1901 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1902 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1912 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1913 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1914 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1916 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1918 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1919 // gravity true/false
1920 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1922 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1923 SV_FlushBroadcastMessages();
1926 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1928 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1929 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1931 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1932 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1934 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1936 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1942 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1943 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1944 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1946 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1948 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1949 SV_FlushBroadcastMessages();
1952 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1954 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1955 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1957 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1958 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1964 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1965 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1970 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1972 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1974 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1975 SV_FlushBroadcastMessages();
1978 static void VM_SV_te_spark(prvm_prog_t *prog)
1980 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1981 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1983 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1984 MSG_WriteByte(&sv.datagram, TE_SPARK);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1990 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1991 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1992 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1994 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1995 SV_FlushBroadcastMessages();
1998 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2000 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2001 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2002 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2004 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2005 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2006 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2007 SV_FlushBroadcastMessages();
2010 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2012 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2013 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2014 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2016 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2017 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2018 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2019 SV_FlushBroadcastMessages();
2022 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2024 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2025 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2026 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2028 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2029 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2030 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2031 SV_FlushBroadcastMessages();
2034 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2036 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2037 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2038 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2040 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2041 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2042 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2043 SV_FlushBroadcastMessages();
2046 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2048 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2049 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2050 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2052 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2054 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2055 SV_FlushBroadcastMessages();
2058 static void VM_SV_te_customflash(prvm_prog_t *prog)
2060 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2061 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2063 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2064 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2066 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2067 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2068 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2070 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2072 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2074 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2075 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2076 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2077 SV_FlushBroadcastMessages();
2080 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2082 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2083 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2084 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2086 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2087 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2088 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2089 SV_FlushBroadcastMessages();
2092 static void VM_SV_te_spike(prvm_prog_t *prog)
2094 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2095 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2096 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2098 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2099 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2100 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2101 SV_FlushBroadcastMessages();
2104 static void VM_SV_te_superspike(prvm_prog_t *prog)
2106 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2107 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2108 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2110 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2111 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2112 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2113 SV_FlushBroadcastMessages();
2116 static void VM_SV_te_explosion(prvm_prog_t *prog)
2118 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2119 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2120 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2122 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2123 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2124 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2125 SV_FlushBroadcastMessages();
2128 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2130 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2131 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2132 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2134 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2135 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2136 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2137 SV_FlushBroadcastMessages();
2140 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2142 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2143 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2144 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2146 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2147 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2148 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2149 SV_FlushBroadcastMessages();
2152 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2154 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2155 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2156 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2158 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2159 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2160 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2161 SV_FlushBroadcastMessages();
2164 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2166 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2167 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2168 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2170 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2171 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2172 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2173 SV_FlushBroadcastMessages();
2176 static void VM_SV_te_teleport(prvm_prog_t *prog)
2178 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2179 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2180 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2182 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2183 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2184 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2185 SV_FlushBroadcastMessages();
2188 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2190 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2191 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2192 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2194 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2195 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2196 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2198 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2199 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2200 SV_FlushBroadcastMessages();
2203 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2205 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2206 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2207 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2209 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2211 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2212 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2213 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2215 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2216 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2217 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2218 SV_FlushBroadcastMessages();
2221 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2223 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2224 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2225 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2227 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2230 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2231 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2234 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2235 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2236 SV_FlushBroadcastMessages();
2239 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2241 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2242 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2243 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2245 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2247 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2248 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2249 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2251 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2252 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2253 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2254 SV_FlushBroadcastMessages();
2257 static void VM_SV_te_beam(prvm_prog_t *prog)
2259 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2260 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2261 MSG_WriteByte(&sv.datagram, TE_BEAM);
2263 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2265 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2266 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2267 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2269 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2270 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2271 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2272 SV_FlushBroadcastMessages();
2275 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2277 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2278 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2279 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2280 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2281 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2282 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2283 SV_FlushBroadcastMessages();
2286 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2288 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2289 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2290 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2292 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2293 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2294 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2296 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2297 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2298 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2300 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2301 SV_FlushBroadcastMessages();
2304 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2305 //this function originally written by KrimZon, made shorter by LordHavoc
2306 static void VM_SV_clientcommand(prvm_prog_t *prog)
2308 client_t *temp_client;
2310 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2312 //find client for this entity
2313 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2314 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2316 Con_Print("PF_clientcommand: entity is not a client\n");
2320 temp_client = host_client;
2321 host_client = svs.clients + i;
2322 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
2323 host_client = temp_client;
2326 //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)
2327 static void VM_SV_setattachment(prvm_prog_t *prog)
2329 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2330 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2331 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2334 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2336 if (e == prog->edicts)
2338 VM_Warning(prog, "setattachment: can not modify world entity\n");
2341 if (e->priv.server->free)
2343 VM_Warning(prog, "setattachment: can not modify free entity\n");
2347 if (tagentity == NULL)
2348 tagentity = prog->edicts;
2352 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2354 model = SV_GetModelFromEdict(tagentity);
2357 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2359 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);
2362 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));
2365 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2366 PRVM_serveredictfloat(e, tag_index) = tagindex;
2369 /////////////////////////////////////////
2370 // DP_MD3_TAGINFO extension coded by VorteX
2372 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2376 i = (int)PRVM_serveredictfloat(e, modelindex);
2377 if (i < 1 || i >= MAX_MODELS)
2380 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2383 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2390 Matrix4x4_CreateIdentity(tag_localmatrix);
2392 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2394 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2405 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2408 float pitchsign = 1;
2410 scale = PRVM_serveredictfloat(ent, scale);
2415 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);
2418 pitchsign = SV_GetPitchSign(prog, ent);
2419 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);
2423 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2426 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2428 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2429 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2430 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2431 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2433 *out = identitymatrix;
2437 // Warnings/errors code:
2438 // 0 - normal (everything all-right)
2441 // 3 - null or non-precached model
2442 // 4 - no tags with requested index
2443 // 5 - runaway loop at attachment chain
2444 extern cvar_t cl_bob;
2445 extern cvar_t cl_bobcycle;
2446 extern cvar_t cl_bobup;
2447 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2450 int modelindex, attachloop;
2451 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2454 *out = identitymatrix; // warnings and errors return identical matrix
2456 if (ent == prog->edicts)
2458 if (ent->priv.server->free)
2461 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2462 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2465 model = SV_GetModelByIndex(modelindex);
2467 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2468 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2469 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2471 tagmatrix = identitymatrix;
2472 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2476 if (attachloop >= 256) // prevent runaway looping
2478 // apply transformation by child's tagindex on parent entity and then
2479 // by parent entity itself
2480 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2481 if (ret && attachloop == 0)
2483 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2484 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2485 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2486 // next iteration we process the parent entity
2487 if (PRVM_serveredictedict(ent, tag_entity))
2489 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2490 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2497 // RENDER_VIEWMODEL magic
2498 if (PRVM_serveredictedict(ent, viewmodelforclient))
2500 Matrix4x4_Copy(&tagmatrix, out);
2501 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2503 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2504 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2507 // Cl_bob, ported from rendering code
2508 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2511 // LordHavoc: this code is *weird*, but not replacable (I think it
2512 // should be done in QC on the server, but oh well, quake is quake)
2513 // LordHavoc: figured out bobup: the time at which the sin is at 180
2514 // degrees (which allows lengthening or squishing the peak or valley)
2515 cycle = sv.time/cl_bobcycle.value;
2516 cycle -= (int)cycle;
2517 if (cycle < cl_bobup.value)
2518 cycle = sin(M_PI * cycle / cl_bobup.value);
2520 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2521 // bob is proportional to velocity in the xy plane
2522 // (don't count Z, or jumping messes it up)
2523 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;
2524 bob = bob*0.3 + bob*0.7*cycle;
2525 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2532 //float(entity ent, string tagname) gettagindex;
2534 static void VM_SV_gettagindex(prvm_prog_t *prog)
2537 const char *tag_name;
2540 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2542 ent = PRVM_G_EDICT(OFS_PARM0);
2543 tag_name = PRVM_G_STRING(OFS_PARM1);
2545 if (ent == prog->edicts)
2547 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2550 if (ent->priv.server->free)
2552 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2557 if (!SV_GetModelFromEdict(ent))
2558 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2561 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2563 if(developer_extra.integer)
2564 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2566 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2569 //vector(entity ent, float tagindex) gettaginfo;
2570 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2574 matrix4x4_t tag_matrix;
2575 matrix4x4_t tag_localmatrix;
2577 const char *tagname;
2579 vec3_t fo, le, up, trans;
2580 const dp_model_t *model;
2582 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2584 e = PRVM_G_EDICT(OFS_PARM0);
2585 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2587 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2588 Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
2589 VectorScale(le, -1, PRVM_serverglobalvector(v_right));
2590 model = SV_GetModelFromEdict(e);
2591 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2592 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
2593 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2594 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2595 Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2597 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2598 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2599 VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
2600 VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
2601 VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
2602 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2607 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2610 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2613 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2616 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2619 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2624 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2625 static void VM_SV_dropclient(prvm_prog_t *prog)
2628 client_t *oldhostclient;
2629 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2630 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2631 if (clientnum < 0 || clientnum >= svs.maxclients)
2633 VM_Warning(prog, "dropclient: not a client\n");
2636 if (!svs.clients[clientnum].active)
2638 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2641 oldhostclient = host_client;
2642 host_client = svs.clients + clientnum;
2643 SV_DropClient(false);
2644 host_client = oldhostclient;
2647 //entity() spawnclient (DP_SV_BOTCLIENT)
2648 static void VM_SV_spawnclient(prvm_prog_t *prog)
2652 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2653 prog->xfunction->builtinsprofile += 2;
2655 for (i = 0;i < svs.maxclients;i++)
2657 if (!svs.clients[i].active)
2659 prog->xfunction->builtinsprofile += 100;
2660 SV_ConnectClient (i, NULL);
2661 // this has to be set or else ClientDisconnect won't be called
2662 // we assume the qc will call ClientConnect...
2663 svs.clients[i].clientconnectcalled = true;
2664 ed = PRVM_EDICT_NUM(i + 1);
2668 VM_RETURN_EDICT(ed);
2671 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2672 static void VM_SV_clienttype(prvm_prog_t *prog)
2675 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2676 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2677 if (clientnum < 0 || clientnum >= svs.maxclients)
2678 PRVM_G_FLOAT(OFS_RETURN) = 3;
2679 else if (!svs.clients[clientnum].active)
2680 PRVM_G_FLOAT(OFS_RETURN) = 0;
2681 else if (svs.clients[clientnum].netconnection)
2682 PRVM_G_FLOAT(OFS_RETURN) = 1;
2684 PRVM_G_FLOAT(OFS_RETURN) = 2;
2691 string(string key) serverkey
2694 static void VM_SV_serverkey(prvm_prog_t *prog)
2696 char string[VM_STRINGTEMP_LENGTH];
2697 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2698 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2699 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2702 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2703 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2708 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2710 e = PRVM_G_EDICT(OFS_PARM0);
2711 if (e == prog->edicts)
2713 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2716 if (e->priv.server->free)
2718 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2721 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2722 if (i <= 0 || i >= MAX_MODELS)
2724 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2727 if (!sv.model_precache[i][0])
2729 VM_Warning(prog, "setmodelindex: model not precached\n");
2733 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2734 PRVM_serveredictfloat(e, modelindex) = i;
2736 mod = SV_GetModelByIndex(i);
2740 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2741 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2743 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2746 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2749 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2750 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2753 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2755 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2757 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2758 if (i <= 0 || i >= MAX_MODELS)
2760 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2763 if (!sv.model_precache[i][0])
2765 VM_Warning(prog, "modelnameforindex: model not precached\n");
2769 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2772 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2773 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2776 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2777 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2780 PRVM_G_FLOAT(OFS_RETURN) = i;
2783 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2784 static void VM_SV_trailparticles(prvm_prog_t *prog)
2786 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2788 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2791 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2792 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2793 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2794 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2795 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2796 SV_FlushBroadcastMessages();
2799 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2800 static void VM_SV_pointparticles(prvm_prog_t *prog)
2802 int effectnum, count;
2804 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2806 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2809 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2810 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2811 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2812 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2813 if (count == 1 && !VectorLength2(vel))
2816 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2817 MSG_WriteShort(&sv.datagram, effectnum);
2818 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2822 // 1+2+12+12+2=29 bytes
2823 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2824 MSG_WriteShort(&sv.datagram, effectnum);
2825 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2826 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2827 MSG_WriteShort(&sv.datagram, count);
2830 SV_FlushBroadcastMessages();
2833 //PF_setpause, // void(float pause) setpause = #531;
2834 static void VM_SV_setpause(prvm_prog_t *prog) {
2836 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2837 if (pauseValue != 0) { //pause the game
2839 sv.pausedstart = realtime;
2840 } else { //disable pause, in case it was enabled
2841 if (sv.paused != 0) {
2846 // send notification to all clients
2847 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2848 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2851 // #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.
2852 static void VM_SV_skel_create(prvm_prog_t *prog)
2854 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2855 dp_model_t *model = SV_GetModelByIndex(modelindex);
2856 skeleton_t *skeleton;
2858 PRVM_G_FLOAT(OFS_RETURN) = 0;
2859 if (!model || !model->num_bones)
2861 for (i = 0;i < MAX_EDICTS;i++)
2862 if (!prog->skeletons[i])
2864 if (i == MAX_EDICTS)
2866 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2867 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2868 skeleton->model = model;
2869 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2870 // initialize to identity matrices
2871 for (i = 0;i < skeleton->model->num_bones;i++)
2872 skeleton->relativetransforms[i] = identitymatrix;
2875 // #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
2876 static void VM_SV_skel_build(prvm_prog_t *prog)
2878 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2879 skeleton_t *skeleton;
2880 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2881 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2882 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2883 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2884 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2885 dp_model_t *model = SV_GetModelByIndex(modelindex);
2890 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2891 frameblend_t frameblend[MAX_FRAMEBLENDS];
2892 matrix4x4_t blendedmatrix;
2894 PRVM_G_FLOAT(OFS_RETURN) = 0;
2895 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2897 firstbone = max(0, firstbone);
2898 lastbone = min(lastbone, model->num_bones - 1);
2899 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2900 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2901 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
2902 blendfrac = 1.0f - retainfrac;
2903 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2904 frameblend[numblends].lerp *= blendfrac;
2905 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2907 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2908 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2909 for (blendindex = 0;blendindex < numblends;blendindex++)
2911 Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2912 Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2914 skeleton->relativetransforms[bonenum] = blendedmatrix;
2916 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2919 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2920 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
2922 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2923 skeleton_t *skeleton;
2924 PRVM_G_FLOAT(OFS_RETURN) = 0;
2925 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2927 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2930 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2931 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
2933 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2934 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2935 skeleton_t *skeleton;
2936 PRVM_G_INT(OFS_RETURN) = 0;
2937 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2939 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2941 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
2944 // #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)
2945 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
2947 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2948 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2949 skeleton_t *skeleton;
2950 PRVM_G_FLOAT(OFS_RETURN) = 0;
2951 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2953 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2955 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2958 // #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
2959 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
2961 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2962 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2963 skeleton_t *skeleton;
2964 PRVM_G_FLOAT(OFS_RETURN) = 0;
2965 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2967 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2970 // #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)
2971 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
2973 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2974 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2975 skeleton_t *skeleton;
2977 vec3_t forward, left, up, origin;
2978 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2979 VectorClear(PRVM_clientglobalvector(v_forward));
2980 VectorClear(PRVM_clientglobalvector(v_right));
2981 VectorClear(PRVM_clientglobalvector(v_up));
2982 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2984 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2986 matrix = skeleton->relativetransforms[bonenum];
2987 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2988 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
2989 VectorNegate(left, PRVM_clientglobalvector(v_right));
2990 VectorCopy(up, PRVM_clientglobalvector(v_up));
2991 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2994 // #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)
2995 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
2997 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2998 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2999 skeleton_t *skeleton;
3002 vec3_t forward, left, up, origin;
3003 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3004 VectorClear(PRVM_clientglobalvector(v_forward));
3005 VectorClear(PRVM_clientglobalvector(v_right));
3006 VectorClear(PRVM_clientglobalvector(v_up));
3007 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3009 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3011 matrix = skeleton->relativetransforms[bonenum];
3012 // convert to absolute
3013 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3016 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3018 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3019 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3020 VectorNegate(left, PRVM_clientglobalvector(v_right));
3021 VectorCopy(up, PRVM_clientglobalvector(v_up));
3022 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3025 // #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)
3026 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3028 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3029 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3030 vec3_t forward, left, up, origin;
3031 skeleton_t *skeleton;
3033 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3035 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3037 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3038 VectorNegate(PRVM_clientglobalvector(v_right), left);
3039 VectorCopy(PRVM_clientglobalvector(v_up), up);
3040 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3041 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3042 skeleton->relativetransforms[bonenum] = matrix;
3045 // #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)
3046 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3048 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3049 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3050 vec3_t forward, left, up, origin;
3051 skeleton_t *skeleton;
3054 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3056 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3058 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3059 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3060 VectorNegate(PRVM_clientglobalvector(v_right), left);
3061 VectorCopy(PRVM_clientglobalvector(v_up), up);
3062 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3063 temp = skeleton->relativetransforms[bonenum];
3064 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3067 // #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)
3068 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3070 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3071 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3072 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3074 vec3_t forward, left, up, origin;
3075 skeleton_t *skeleton;
3078 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3080 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3081 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3082 VectorNegate(PRVM_clientglobalvector(v_right), left);
3083 VectorCopy(PRVM_clientglobalvector(v_up), up);
3084 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3085 firstbone = max(0, firstbone);
3086 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3087 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3089 temp = skeleton->relativetransforms[bonenum];
3090 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3094 // #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
3095 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3097 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3098 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3099 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3100 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3102 skeleton_t *skeletondst;
3103 skeleton_t *skeletonsrc;
3104 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3106 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3108 firstbone = max(0, firstbone);
3109 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3110 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3111 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3112 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3115 // #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)
3116 static void VM_SV_skel_delete(prvm_prog_t *prog)
3118 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3119 skeleton_t *skeleton;
3120 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3123 prog->skeletons[skeletonindex] = NULL;
3126 // #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
3127 static void VM_SV_frameforname(prvm_prog_t *prog)
3129 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3130 dp_model_t *model = SV_GetModelByIndex(modelindex);
3131 const char *name = PRVM_G_STRING(OFS_PARM1);
3133 PRVM_G_FLOAT(OFS_RETURN) = -1;
3134 if (!model || !model->animscenes)
3136 for (i = 0;i < model->numframes;i++)
3138 if (!strcasecmp(model->animscenes[i].name, name))
3140 PRVM_G_FLOAT(OFS_RETURN) = i;
3146 // #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.
3147 static void VM_SV_frameduration(prvm_prog_t *prog)
3149 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3150 dp_model_t *model = SV_GetModelByIndex(modelindex);
3151 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3152 PRVM_G_FLOAT(OFS_RETURN) = 0;
3153 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3155 if (model->animscenes[framenum].framerate)
3156 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3160 prvm_builtin_t vm_sv_builtins[] = {
3161 NULL, // #0 NULL function (not callable) (QUAKE)
3162 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3163 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3164 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3165 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3166 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3167 VM_break, // #6 void() break (QUAKE)
3168 VM_random, // #7 float() random (QUAKE)
3169 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3170 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3171 VM_error, // #10 void(string e) error (QUAKE)
3172 VM_objerror, // #11 void(string e) objerror (QUAKE)
3173 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3174 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3175 VM_spawn, // #14 entity() spawn (QUAKE)
3176 VM_remove, // #15 void(entity e) remove (QUAKE)
3177 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3178 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3179 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3180 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3181 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3182 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3183 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3184 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3185 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3186 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3187 VM_ftos, // #26 string(float f) ftos (QUAKE)
3188 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3189 VM_coredump, // #28 void() coredump (QUAKE)
3190 VM_traceon, // #29 void() traceon (QUAKE)
3191 VM_traceoff, // #30 void() traceoff (QUAKE)
3192 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3193 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3194 NULL, // #33 (QUAKE)
3195 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3196 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3197 VM_rint, // #36 float(float v) rint (QUAKE)
3198 VM_floor, // #37 float(float v) floor (QUAKE)
3199 VM_ceil, // #38 float(float v) ceil (QUAKE)
3200 NULL, // #39 (QUAKE)
3201 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3202 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3203 NULL, // #42 (QUAKE)
3204 VM_fabs, // #43 float(float f) fabs (QUAKE)
3205 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3206 VM_cvar, // #45 float(string s) cvar (QUAKE)
3207 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3208 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3209 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3210 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3211 NULL, // #50 (QUAKE)
3212 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3213 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3214 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3215 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3216 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3217 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3218 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3219 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3220 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3221 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3222 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3223 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3224 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3225 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3226 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3227 NULL, // #66 (QUAKE)
3228 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3229 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3230 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3231 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3232 NULL, // #71 (QUAKE)
3233 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3234 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3235 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3236 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3237 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3238 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3239 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3240 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3241 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3242 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3243 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3244 NULL, // #83 (QUAKE)
3245 NULL, // #84 (QUAKE)
3246 NULL, // #85 (QUAKE)
3247 NULL, // #86 (QUAKE)
3248 NULL, // #87 (QUAKE)
3249 NULL, // #88 (QUAKE)
3250 NULL, // #89 (QUAKE)
3251 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3252 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3253 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3254 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3255 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3256 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3257 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3258 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3259 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3260 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3261 // FrikaC and Telejano range #100-#199
3272 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3273 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3274 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3275 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3276 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3277 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3278 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3279 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3280 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3281 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3362 // FTEQW range #200-#299
3381 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3384 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3385 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3386 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3387 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3388 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3389 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3390 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3391 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3392 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3393 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3395 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3403 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3426 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.
3427 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
3428 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3429 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3430 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)
3431 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
3432 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)
3433 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)
3434 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)
3435 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)
3436 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)
3437 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
3438 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)
3439 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
3440 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.
3463 // CSQC range #300-#399
3464 NULL, // #300 void() clearscene (EXT_CSQC)
3465 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3466 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3467 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3468 NULL, // #304 void() renderscene (EXT_CSQC)
3469 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3470 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3471 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3472 NULL, // #308 void() R_EndPolygon
3474 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3475 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3479 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3480 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3481 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3482 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3483 NULL, // #319 void(string name) freepic (EXT_CSQC)
3484 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3485 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3486 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3487 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3488 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3489 NULL, // #325 void(void) drawresetcliparea
3494 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3495 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3496 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3497 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3498 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3499 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3500 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3501 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3502 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3503 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3504 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3505 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3506 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3507 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3508 NULL, // #344 vector() getmousepos (EXT_CSQC)
3509 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3510 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3511 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3512 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3513 NULL, // #349 float() isdemo (EXT_CSQC)
3514 VM_isserver, // #350 float() isserver (EXT_CSQC)
3515 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3516 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3517 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3518 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3524 NULL, // #360 float() readbyte (EXT_CSQC)
3525 NULL, // #361 float() readchar (EXT_CSQC)
3526 NULL, // #362 float() readshort (EXT_CSQC)
3527 NULL, // #363 float() readlong (EXT_CSQC)
3528 NULL, // #364 float() readcoord (EXT_CSQC)
3529 NULL, // #365 float() readangle (EXT_CSQC)
3530 NULL, // #366 string() readstring (EXT_CSQC)
3531 NULL, // #367 float() readfloat (EXT_CSQC)
3564 // LordHavoc's range #400-#499
3565 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3566 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3567 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3568 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3569 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3570 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3571 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3572 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3573 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)
3574 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3575 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3576 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3577 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3578 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3579 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3580 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3581 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3582 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3583 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3584 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3585 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3586 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3587 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3588 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3589 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3590 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3591 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3592 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3593 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3594 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3595 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3596 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3597 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3598 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3599 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3600 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3601 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3602 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3603 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3604 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3605 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3606 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3607 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3608 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3609 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3610 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3611 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3612 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3613 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3614 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3615 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3616 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3617 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3618 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3619 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3620 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3621 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3622 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3624 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3625 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3626 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3627 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3628 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3629 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3630 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3631 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3632 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3633 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3634 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3636 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3637 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3638 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3639 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3640 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3641 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3642 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3643 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3644 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3645 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3646 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3647 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3648 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3649 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3650 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3651 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3659 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3660 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3661 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3662 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3663 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3664 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3665 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3666 VM_SV_WritePicture, // #501
3668 VM_whichpack, // #503 string(string) whichpack = #503;
3675 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3676 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3677 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3678 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)
3679 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3680 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3681 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3682 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3683 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3684 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3694 VM_loadfromdata, // #529
3695 VM_loadfromfile, // #530
3696 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3698 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3699 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3705 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3706 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3707 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3770 VM_callfunction, // #605
3771 VM_writetofile, // #606
3772 VM_isfunction, // #607
3778 VM_parseentitydata, // #613
3789 VM_SV_getextresponse, // #624 string getextresponse(void)
3792 VM_sprintf, // #627 string sprintf(string format, ...)
3793 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3794 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3804 VM_digest_hex, // #639
3808 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3810 void SVVM_init_cmd(prvm_prog_t *prog)
3815 void SVVM_reset_cmd(prvm_prog_t *prog)
3817 World_End(&sv.world);
3818 if(PRVM_serverfunction(SV_Shutdown))
3820 func_t s = PRVM_serverfunction(SV_Shutdown);
3821 PRVM_serverglobalfloat(time) = sv.time;
3822 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3823 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");