6 //============================================================================
11 const char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
25 "DP_CSQC_ENTITYWORLDOBJECT "
26 "DP_CSQC_ENTITYMODELLIGHT "
27 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
29 "DP_CSQC_MINFPS_QUALITY "
30 "DP_CSQC_MULTIFRAME_INTERPOLATION "
31 "DP_CSQC_BOXPARTICLES "
32 "DP_CSQC_SPAWNPARTICLE "
33 "DP_CSQC_QUERYRENDERENTITY "
34 "DP_CSQC_ROTATEMOVES "
36 "DP_CSQC_V_CALCREFDEF_WIP1 "
37 "DP_CSQC_V_CALCREFDEF_WIP2 "
41 "DP_EF_DYNAMICMODELLIGHT "
50 "DP_EF_RESTARTANIM_BIT "
55 "DP_ENT_CUSTOMCOLORMAP "
56 "DP_ENT_EXTERIORMODELTOCLIENT "
59 "DP_ENT_LOWPRECISION "
61 "DP_ENT_TRAILEFFECTNUM "
63 "DP_GFX_EXTERNALTEXTURES "
64 "DP_GFX_EXTERNALTEXTURES_PERMAP "
66 "DP_GFX_MODEL_INTERPOLATION "
67 "DP_GFX_QUAKE3MODELTAGS "
71 "DP_GFX_FONTS_FREETYPE "
73 "DP_FONT_VARIABLEWIDTH "
75 "DP_HALFLIFE_MAP_CVAR "
78 "DP_LIGHTSTYLE_STATICVALUE "
82 "DP_MOVETYPEBOUNCEMISSILE "
83 "DP_MOVETYPEFLYWORLDONLY "
86 "DP_QC_ASINACOSATANATAN2TAN "
92 "DP_QC_CVAR_DEFSTRING "
93 "DP_QC_CVAR_DESCRIPTION "
97 "DP_QC_DIGEST_SHA256 "
100 "DP_QC_ENTITYSTRING "
102 "DP_QC_EXTRESPONSEPACKET "
104 "DP_QC_FINDCHAINFLAGS "
105 "DP_QC_FINDCHAINFLOAT "
106 "DP_QC_FINDCHAIN_TOFIELD "
112 "DP_QC_GETSURFACETRIANGLE "
113 "DP_QC_GETSURFACEPOINTATTRIBUTE "
115 "DP_QC_GETTAGINFO_BONEPROPERTIES "
117 "DP_QC_GETTIME_CDTRACK "
121 "DP_QC_MULTIPLETEMPSTRINGS "
122 "DP_QC_NUM_FOR_EDICT "
124 "DP_QC_SINCOSSQRTPOW "
127 "DP_QC_STRINGBUFFERS "
128 "DP_QC_STRINGBUFFERS_CVARLIST "
129 "DP_QC_STRINGBUFFERS_EXT_WIP "
130 "DP_QC_STRINGCOLORFUNCTIONS "
131 "DP_QC_STRING_CASE_FUNCTIONS "
133 "DP_QC_TOKENIZEBYSEPARATOR "
134 "DP_QC_TOKENIZE_CONSOLE "
137 "DP_QC_TRACE_MOVETYPE_HITMODEL "
138 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
139 "DP_QC_UNLIMITEDTEMPSTRINGS "
143 "DP_QC_VECTOANGLES_WITH_ROLL "
144 "DP_QC_VECTORVECTORS "
151 "DP_SKELETONOBJECTS "
152 "DP_SND_DIRECTIONLESSATTNNONE "
154 "DP_SND_SOUND7_WIP1 "
155 "DP_SND_SOUND7_WIP2 "
159 "DP_SND_GETSOUNDTIME "
161 "DP_VIDEO_SUBTITLES "
165 "DP_SV_BOUNCEFACTOR "
166 "DP_SV_CLIENTCAMERA "
167 "DP_SV_CLIENTCOLORS "
170 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
171 "DP_SV_DISABLECLIENTPREDICTION "
172 "DP_SV_DISCARDABLEDEMO "
173 "DP_SV_DRAWONLYTOCLIENT "
176 "DP_SV_ENTITYCONTENTSTRANSITION "
177 "DP_SV_MODELFLAGS_AS_EFFECTS "
178 "DP_SV_MOVETYPESTEP_LANDEVENT "
180 "DP_SV_NODRAWTOCLIENT "
181 "DP_SV_ONENTITYNOSPAWNFUNCTION "
182 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
184 "DP_SV_PING_PACKETLOSS "
185 "DP_SV_PLAYERPHYSICS "
187 "DP_SV_POINTPARTICLES "
189 "DP_SV_PRECACHEANYTIME "
193 "DP_SV_ROTATINGBMODEL "
197 "DP_SV_SPAWNFUNC_PREFIX "
198 "DP_SV_WRITEPICTURE "
199 "DP_SV_WRITEUNTERMINATEDSTRING "
203 "DP_TE_EXPLOSIONRGB "
205 "DP_TE_PARTICLECUBE "
206 "DP_TE_PARTICLERAIN "
207 "DP_TE_PARTICLESNOW "
209 "DP_TE_QUADEFFECTS1 "
212 "DP_TE_STANDARDEFFECTBUILTINS "
213 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
218 "FTE_CSQC_SKELETONOBJECTS "
221 "KRIMZON_SV_PARSECLIENTCOMMAND "
224 "NEXUIZ_PLAYERMODEL "
226 "PRYDON_CLIENTCURSOR "
227 "TENEBRAE_GFX_DLIGHTS "
230 //"EXT_CSQC " // not ready yet
237 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.
239 setorigin (entity, origin)
242 static void VM_SV_setorigin(prvm_prog_t *prog)
246 VM_SAFEPARMCOUNT(2, VM_setorigin);
248 e = PRVM_G_EDICT(OFS_PARM0);
249 if (e == prog->edicts)
251 VM_Warning(prog, "setorigin: can not modify world entity\n");
254 if (e->priv.server->free)
256 VM_Warning(prog, "setorigin: can not modify free entity\n");
259 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), PRVM_serveredictvector(e, origin));
260 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
261 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
265 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
266 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qboolean rotate)
270 for (i=0 ; i<3 ; i++)
272 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
274 // set derived values
275 VectorCopy (min, PRVM_serveredictvector(e, mins));
276 VectorCopy (max, PRVM_serveredictvector(e, maxs));
277 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
286 the size box is rotated by the current angle
287 LordHavoc: no it isn't...
289 setsize (entity, minvector, maxvector)
292 static void VM_SV_setsize(prvm_prog_t *prog)
297 VM_SAFEPARMCOUNT(3, VM_setsize);
299 e = PRVM_G_EDICT(OFS_PARM0);
300 if (e == prog->edicts)
302 VM_Warning(prog, "setsize: can not modify world entity\n");
305 if (e->priv.server->free)
307 VM_Warning(prog, "setsize: can not modify free entity\n");
310 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), mins);
311 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), maxs);
312 SetMinMaxSize(prog, e, mins, maxs, false);
320 setmodel(entity, model)
323 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
324 static void VM_SV_setmodel(prvm_prog_t *prog)
330 VM_SAFEPARMCOUNT(2, VM_setmodel);
332 e = PRVM_G_EDICT(OFS_PARM0);
333 if (e == prog->edicts)
335 VM_Warning(prog, "setmodel: can not modify world entity\n");
338 if (e->priv.server->free)
340 VM_Warning(prog, "setmodel: can not modify free entity\n");
343 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
344 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
345 PRVM_serveredictfloat(e, modelindex) = i;
347 mod = SV_GetModelByIndex(i);
351 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
352 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
354 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
357 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
364 single print to a specific client
366 sprint(clientent, value)
369 static void VM_SV_sprint(prvm_prog_t *prog)
373 char string[VM_STRINGTEMP_LENGTH];
375 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
377 VM_VarString(prog, 1, string, sizeof(string));
379 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
380 // LordHavoc: div0 requested that sprintto world operate like print
387 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
389 VM_Warning(prog, "tried to centerprint to a non-client\n");
393 client = svs.clients + entnum-1;
394 if (!client->netconnection)
397 MSG_WriteChar(&client->netconnection->message,svc_print);
398 MSG_WriteString(&client->netconnection->message, string);
406 single print to a specific client
408 centerprint(clientent, value)
411 static void VM_SV_centerprint(prvm_prog_t *prog)
415 char string[VM_STRINGTEMP_LENGTH];
417 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
419 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
421 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
423 VM_Warning(prog, "tried to centerprint to a non-client\n");
427 client = svs.clients + entnum-1;
428 if (!client->netconnection)
431 VM_VarString(prog, 1, string, sizeof(string));
432 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
433 MSG_WriteString(&client->netconnection->message, string);
440 particle(origin, color, count)
443 static void VM_SV_particle(prvm_prog_t *prog)
449 VM_SAFEPARMCOUNT(4, VM_SV_particle);
451 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
452 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
453 color = (int)PRVM_G_FLOAT(OFS_PARM2);
454 count = (int)PRVM_G_FLOAT(OFS_PARM3);
455 SV_StartParticle (org, dir, color, count);
465 static void VM_SV_ambientsound(prvm_prog_t *prog)
469 prvm_vec_t vol, attenuation;
472 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
474 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
475 samp = PRVM_G_STRING(OFS_PARM1);
476 vol = PRVM_G_FLOAT(OFS_PARM2);
477 attenuation = PRVM_G_FLOAT(OFS_PARM3);
479 // check to see if samp was properly precached
480 soundnum = SV_SoundIndex(samp, 1);
488 // add an svc_spawnambient command to the level signon packet
491 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
493 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
495 MSG_WriteVector(&sv.signon, pos, sv.protocol);
497 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
498 MSG_WriteShort (&sv.signon, soundnum);
500 MSG_WriteByte (&sv.signon, soundnum);
502 MSG_WriteByte (&sv.signon, (int)(vol*255));
503 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
511 Each entity can have eight independant sound sources, like voice,
514 Channel 0 is an auto-allocate channel, the others override anything
515 already running on that entity/channel pair.
517 An attenuation of 0 will play full volume everywhere in the level.
518 Larger attenuations will drop off.
522 static void VM_SV_sound(prvm_prog_t *prog)
526 prvm_edict_t *entity;
532 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
534 entity = PRVM_G_EDICT(OFS_PARM0);
535 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
536 sample = PRVM_G_STRING(OFS_PARM2);
537 nvolume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
540 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
544 attenuation = PRVM_G_FLOAT(OFS_PARM4);
548 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
553 if(channel >= 8 && channel <= 15) // weird QW feature
555 flags |= CHANNELFLAG_RELIABLE;
561 // LordHavoc: we only let the qc set certain flags, others are off-limits
562 flags = (int)PRVM_G_FLOAT(OFS_PARM6) & (CHANNELFLAG_RELIABLE | CHANNELFLAG_FORCELOOP | CHANNELFLAG_PAUSED | CHANNELFLAG_FULLVOLUME);
565 if (nvolume < 0 || nvolume > 255)
567 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
571 if (attenuation < 0 || attenuation > 4)
573 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
577 channel = CHAN_USER2ENGINE(channel);
579 if (!IS_CHAN(channel))
581 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
585 SV_StartSound (entity, channel, sample, nvolume, attenuation, flags & CHANNELFLAG_RELIABLE, pitchchange);
592 Follows the same logic as VM_SV_sound, except instead of
593 an entity, an origin for the sound is provided, and channel
594 is omitted (since no entity is being tracked).
598 static void VM_SV_pointsound(prvm_prog_t *prog)
606 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
608 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
609 sample = PRVM_G_STRING(OFS_PARM1);
610 nvolume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
611 attenuation = PRVM_G_FLOAT(OFS_PARM3);
612 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
614 if (nvolume < 0 || nvolume > 255)
616 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
620 if (attenuation < 0 || attenuation > 4)
622 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
626 SV_StartPointSound (org, sample, nvolume, attenuation, pitchchange);
633 Used for use tracing and shot targeting
634 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
635 if the tryents flag is set.
637 traceline (vector1, vector2, movetype, ignore)
640 static void VM_SV_traceline(prvm_prog_t *prog)
647 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
649 prog->xfunction->builtinsprofile += 30;
651 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
652 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), v2);
653 move = (int)PRVM_G_FLOAT(OFS_PARM2);
654 ent = PRVM_G_EDICT(OFS_PARM3);
656 if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_IS_NAN(v2[2]))
657 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));
659 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtracelinelength.value);
661 VM_SetTraceGlobals(prog, &trace);
669 Used for use tracing and shot targeting
670 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
671 if the tryents flag is set.
673 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
676 // LordHavoc: added this for my own use, VERY useful, similar to traceline
677 static void VM_SV_tracebox(prvm_prog_t *prog)
679 vec3_t v1, v2, m1, m2;
684 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
686 prog->xfunction->builtinsprofile += 30;
688 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
689 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), m1);
690 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), m2);
691 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), v2);
692 move = (int)PRVM_G_FLOAT(OFS_PARM4);
693 ent = PRVM_G_EDICT(OFS_PARM5);
695 if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_IS_NAN(v2[2]))
696 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));
698 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtraceboxlength.value);
700 VM_SetTraceGlobals(prog, &trace);
703 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
707 vec3_t move, end, tossentorigin, tossentmins, tossentmaxs;
708 vec3_t original_origin;
709 vec3_t original_velocity;
710 vec3_t original_angles;
711 vec3_t original_avelocity;
714 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
715 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
716 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
717 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
719 gravity = PRVM_serveredictfloat(tossent, gravity);
722 gravity *= sv_gravity.value * 0.025;
724 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
726 SV_CheckVelocity (tossent);
727 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
728 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
729 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
730 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
731 VectorCopy(PRVM_serveredictvector(tossent, origin), tossentorigin);
732 VectorCopy(PRVM_serveredictvector(tossent, mins), tossentmins);
733 VectorCopy(PRVM_serveredictvector(tossent, maxs), tossentmaxs);
734 trace = SV_TraceBox(tossentorigin, tossentmins, tossentmaxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent), 0, 0, collision_extendmovelength.value);
735 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
736 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
738 if (trace.fraction < 1)
742 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
743 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
744 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
745 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
750 static void VM_SV_tracetoss(prvm_prog_t *prog)
754 prvm_edict_t *ignore;
756 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
758 prog->xfunction->builtinsprofile += 600;
760 ent = PRVM_G_EDICT(OFS_PARM0);
761 if (ent == prog->edicts)
763 VM_Warning(prog, "tracetoss: can not use world entity\n");
766 ignore = PRVM_G_EDICT(OFS_PARM1);
768 trace = SV_Trace_Toss(prog, ent, ignore);
770 VM_SetTraceGlobals(prog, &trace);
773 //============================================================================
775 static int checkpvsbytes;
776 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
778 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
784 // cycle to the next one
786 check = bound(1, check, svs.maxclients);
787 if (check == svs.maxclients)
795 prog->xfunction->builtinsprofile++;
797 if (i == svs.maxclients+1)
799 // look up the client's edict
800 ent = PRVM_EDICT_NUM(i);
801 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
802 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
804 // found a valid client (possibly the same one again)
808 // get the PVS for the entity
809 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
811 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
812 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
821 Returns a client (or object that has a client enemy) that would be a
824 If there is more than one valid option, they are cycled each frame
826 If (self.origin + self.viewofs) is not in the PVS of the current target,
827 it is not returned at all.
832 int c_invis, c_notvis;
833 static void VM_SV_checkclient(prvm_prog_t *prog)
835 prvm_edict_t *ent, *self;
838 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
840 // find a new check if on a new frame
841 if (sv.time - sv.lastchecktime >= 0.1)
843 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
844 sv.lastchecktime = sv.time;
847 // return check if it might be visible
848 ent = PRVM_EDICT_NUM(sv.lastcheck);
849 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
851 VM_RETURN_EDICT(prog->edicts);
855 // if current entity can't possibly see the check entity, return 0
856 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
857 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
858 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
861 VM_RETURN_EDICT(prog->edicts);
865 // might be able to see it
867 VM_RETURN_EDICT(ent);
870 //============================================================================
876 Checks if an entity is in a point's PVS.
877 Should be fast but can be inexact.
879 float checkpvs(vector viewpos, entity viewee) = #240;
882 static void VM_SV_checkpvs(prvm_prog_t *prog)
884 vec3_t viewpos, absmin, absmax;
885 prvm_edict_t *viewee;
890 unsigned char fatpvs[MAX_MAP_LEAFS/8];
893 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
894 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
895 viewee = PRVM_G_EDICT(OFS_PARM1);
897 if(viewee->priv.server->free)
899 VM_Warning(prog, "checkpvs: can not check free entity\n");
900 PRVM_G_FLOAT(OFS_RETURN) = 4;
905 if(!sv.worldmodel || !sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
907 // no PVS support on this worldmodel... darn
908 PRVM_G_FLOAT(OFS_RETURN) = 3;
911 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
914 // viewpos isn't in any PVS... darn
915 PRVM_G_FLOAT(OFS_RETURN) = 2;
918 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
919 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
920 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, absmin, absmax);
922 // using fat PVS like FTEQW does (slow)
923 if(!sv.worldmodel || !sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
925 // no PVS support on this worldmodel... darn
926 PRVM_G_FLOAT(OFS_RETURN) = 3;
929 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
932 // viewpos isn't in any PVS... darn
933 PRVM_G_FLOAT(OFS_RETURN) = 2;
936 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
937 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
938 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, absmin, absmax);
947 Sends text over to the client's execution buffer
949 stuffcmd (clientent, value, ...)
952 static void VM_SV_stuffcmd(prvm_prog_t *prog)
956 char string[VM_STRINGTEMP_LENGTH];
958 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
960 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
961 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
963 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
967 VM_VarString(prog, 1, string, sizeof(string));
970 host_client = svs.clients + entnum-1;
971 Host_ClientCommands ("%s", string);
979 Returns a chain of entities that have origins within a spherical area
981 findradius (origin, radius)
984 static void VM_SV_findradius(prvm_prog_t *prog)
986 prvm_edict_t *ent, *chain;
987 vec_t radius, radius2;
988 vec3_t org, eorg, mins, maxs;
991 static prvm_edict_t *touchedicts[MAX_EDICTS];
994 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
997 chainfield = PRVM_G_INT(OFS_PARM2);
999 chainfield = prog->fieldoffsets.chain;
1001 prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
1003 chain = (prvm_edict_t *)prog->edicts;
1005 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1006 radius = PRVM_G_FLOAT(OFS_PARM1);
1007 radius2 = radius * radius;
1009 mins[0] = org[0] - (radius + 1);
1010 mins[1] = org[1] - (radius + 1);
1011 mins[2] = org[2] - (radius + 1);
1012 maxs[0] = org[0] + (radius + 1);
1013 maxs[1] = org[1] + (radius + 1);
1014 maxs[2] = org[2] + (radius + 1);
1015 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1016 if (numtouchedicts > MAX_EDICTS)
1018 // this never happens
1019 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1020 numtouchedicts = MAX_EDICTS;
1022 for (i = 0;i < numtouchedicts;i++)
1024 ent = touchedicts[i];
1025 prog->xfunction->builtinsprofile++;
1026 // Quake did not return non-solid entities but darkplaces does
1027 // (note: this is the reason you can't blow up fallen zombies)
1028 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1030 // LordHavoc: compare against bounding box rather than center so it
1031 // doesn't miss large objects, and use DotProduct instead of Length
1032 // for a major speedup
1033 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1034 if (sv_gameplayfix_findradiusdistancetobox.integer)
1036 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1037 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1038 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1041 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1042 if (DotProduct(eorg, eorg) < radius2)
1044 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1049 VM_RETURN_EDICT(chain);
1052 static void VM_SV_precache_sound(prvm_prog_t *prog)
1054 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1055 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1058 static void VM_SV_precache_model(prvm_prog_t *prog)
1060 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1061 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1062 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1069 float(float yaw, float dist[, settrace]) walkmove
1072 static void VM_SV_walkmove(prvm_prog_t *prog)
1081 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1083 // assume failure if it returns early
1084 PRVM_G_FLOAT(OFS_RETURN) = 0;
1086 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1087 if (ent == prog->edicts)
1089 VM_Warning(prog, "walkmove: can not modify world entity\n");
1092 if (ent->priv.server->free)
1094 VM_Warning(prog, "walkmove: can not modify free entity\n");
1097 yaw = PRVM_G_FLOAT(OFS_PARM0);
1098 dist = PRVM_G_FLOAT(OFS_PARM1);
1099 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1101 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1104 yaw = yaw*M_PI*2 / 360;
1106 move[0] = cos(yaw)*dist;
1107 move[1] = sin(yaw)*dist;
1110 // save program state, because SV_movestep may call other progs
1111 oldf = prog->xfunction;
1112 oldself = PRVM_serverglobaledict(self);
1114 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1117 // restore program state
1118 prog->xfunction = oldf;
1119 PRVM_serverglobaledict(self) = oldself;
1130 static void VM_SV_droptofloor(prvm_prog_t *prog)
1133 vec3_t end, entorigin, entmins, entmaxs;
1136 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1138 // assume failure if it returns early
1139 PRVM_G_FLOAT(OFS_RETURN) = 0;
1141 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1142 if (ent == prog->edicts)
1144 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1147 if (ent->priv.server->free)
1149 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1153 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1156 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1157 SV_NudgeOutOfSolid(ent);
1159 VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
1160 VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
1161 VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
1162 trace = SV_TraceBox(entorigin, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
1163 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1166 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]);
1167 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1168 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
1169 VectorSubtract(trace.endpos, offset, trace.endpos);
1170 if (trace.startsolid)
1172 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]);
1174 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1175 PRVM_serveredictedict(ent, groundentity) = 0;
1176 PRVM_G_FLOAT(OFS_RETURN) = 1;
1178 else if (trace.fraction < 1)
1180 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]);
1181 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1182 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1183 SV_NudgeOutOfSolid(ent);
1185 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1186 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1187 PRVM_G_FLOAT(OFS_RETURN) = 1;
1188 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1189 ent->priv.server->suspendedinairflag = true;
1194 if (!trace.allsolid && trace.fraction < 1)
1196 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1198 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1199 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1200 PRVM_G_FLOAT(OFS_RETURN) = 1;
1201 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1202 ent->priv.server->suspendedinairflag = true;
1211 void(float style, string value) lightstyle
1214 static void VM_SV_lightstyle(prvm_prog_t *prog)
1221 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1223 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1224 val = PRVM_G_STRING(OFS_PARM1);
1226 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1227 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1230 // change the string in sv
1231 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1233 // send message to all clients on this server
1234 if (sv.state != ss_active)
1237 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1239 if (client->active && client->netconnection)
1241 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1242 MSG_WriteChar (&client->netconnection->message,style);
1243 MSG_WriteString (&client->netconnection->message, val);
1253 static void VM_SV_checkbottom(prvm_prog_t *prog)
1255 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1256 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1264 static void VM_SV_pointcontents(prvm_prog_t *prog)
1267 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1268 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point);
1269 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(SV_PointSuperContents(point));
1276 Pick a vector for the player to shoot along
1277 vector aim(entity, missilespeed)
1280 static void VM_SV_aim(prvm_prog_t *prog)
1282 prvm_edict_t *ent, *check, *bestent;
1283 vec3_t start, dir, end, bestdir;
1286 float dist, bestdist;
1289 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1291 // assume failure if it returns early
1292 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1293 // if sv_aim is so high it can't possibly accept anything, skip out early
1294 if (sv_aim.value >= 1)
1297 ent = PRVM_G_EDICT(OFS_PARM0);
1298 if (ent == prog->edicts)
1300 VM_Warning(prog, "aim: can not use world entity\n");
1303 if (ent->priv.server->free)
1305 VM_Warning(prog, "aim: can not use free entity\n");
1308 //speed = PRVM_G_FLOAT(OFS_PARM1);
1310 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1313 // try sending a trace straight
1314 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1315 VectorMA (start, 2048, dir, end);
1316 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1317 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1318 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1320 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1325 // try all possible entities
1326 VectorCopy (dir, bestdir);
1327 bestdist = sv_aim.value;
1330 check = PRVM_NEXT_EDICT(prog->edicts);
1331 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1333 prog->xfunction->builtinsprofile++;
1334 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1338 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1339 continue; // don't aim at teammate
1340 for (j=0 ; j<3 ; j++)
1341 end[j] = PRVM_serveredictvector(check, origin)[j]
1342 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1343 VectorSubtract (end, start, dir);
1344 VectorNormalize (dir);
1345 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1346 if (dist < bestdist)
1347 continue; // to far to turn
1348 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1349 if (tr.ent == check)
1350 { // can shoot at this one
1358 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1359 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1360 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1362 VectorNormalize (end);
1363 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1367 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1372 ===============================================================================
1376 ===============================================================================
1379 #define MSG_BROADCAST 0 // unreliable to all
1380 #define MSG_ONE 1 // reliable to one (msg_entity)
1381 #define MSG_ALL 2 // reliable to all
1382 #define MSG_INIT 3 // write to the init string
1383 #define MSG_ENTITY 5
1385 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1391 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1395 return &sv.datagram;
1398 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1399 entnum = PRVM_NUM_FOR_EDICT(ent);
1400 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1402 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1403 return &sv.reliable_datagram;
1406 return &svs.clients[entnum-1].netconnection->message;
1409 VM_Warning(prog, "WriteDest: bad destination\n");
1411 return &sv.reliable_datagram;
1417 return sv.writeentitiestoclient_msg;
1423 static void VM_SV_WriteByte(prvm_prog_t *prog)
1425 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1426 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1429 static void VM_SV_WriteChar(prvm_prog_t *prog)
1431 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1432 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1435 static void VM_SV_WriteShort(prvm_prog_t *prog)
1437 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1438 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1441 static void VM_SV_WriteLong(prvm_prog_t *prog)
1443 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1444 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1447 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1449 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1450 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1453 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1455 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1456 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1459 static void VM_SV_WriteString(prvm_prog_t *prog)
1461 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1462 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1465 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1467 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1468 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1472 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1474 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1475 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1478 // writes a picture as at most size bytes of data
1480 // IMGNAME \0 SIZE(short) IMGDATA
1481 // if failed to read/compress:
1483 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1484 static void VM_SV_WritePicture(prvm_prog_t *prog)
1486 const char *imgname;
1490 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1492 imgname = PRVM_G_STRING(OFS_PARM1);
1493 size = (size_t) PRVM_G_FLOAT(OFS_PARM2);
1497 MSG_WriteString(WriteDest(prog), imgname);
1498 if(Image_Compress(imgname, size, &buf, &size))
1501 MSG_WriteShort(WriteDest(prog), (int)size);
1502 SZ_Write(WriteDest(prog), (unsigned char *) buf, (int)size);
1507 MSG_WriteShort(WriteDest(prog), 0);
1511 //////////////////////////////////////////////////////////
1513 static void VM_SV_makestatic(prvm_prog_t *prog)
1518 // allow 0 parameters due to an id1 qc bug in which this function is used
1519 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1520 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1522 if (prog->argc >= 1)
1523 ent = PRVM_G_EDICT(OFS_PARM0);
1525 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1526 if (ent == prog->edicts)
1528 VM_Warning(prog, "makestatic: can not modify world entity\n");
1531 if (ent->priv.server->free)
1533 VM_Warning(prog, "makestatic: can not modify free entity\n");
1538 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1543 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1544 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1545 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1547 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1549 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1550 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1551 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1555 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1556 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1557 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1560 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1561 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1562 for (i=0 ; i<3 ; i++)
1564 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1565 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1568 // throw the entity away now
1569 PRVM_ED_Free(prog, ent);
1572 //=============================================================================
1579 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1585 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1587 ent = PRVM_G_EDICT(OFS_PARM0);
1588 i = PRVM_NUM_FOR_EDICT(ent);
1589 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1591 Con_Print("tried to setspawnparms on a non-client\n");
1595 // copy spawn parms out of the client_t
1596 client = svs.clients + i-1;
1597 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1598 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1605 Returns a color vector indicating the lighting at the requested point.
1607 (Internal Operation note: actually measures the light beneath the point, just like
1608 the model lighting on the client)
1613 static void VM_SV_getlight(prvm_prog_t *prog)
1615 vec3_t ambientcolor, diffusecolor, diffusenormal;
1617 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1618 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
1619 VectorClear(ambientcolor);
1620 VectorClear(diffusecolor);
1621 VectorClear(diffusenormal);
1622 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1623 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1624 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1629 unsigned char type; // 1/2/8 or other value if isn't used
1633 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1634 static int vm_customstats_last;
1636 void VM_CustomStats_Clear (void)
1640 Z_Free(vm_customstats);
1641 vm_customstats = NULL;
1642 vm_customstats_last = -1;
1646 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1648 prvm_prog_t *prog = SVVM_prog;
1659 for(i=0; i<vm_customstats_last+1 ;i++)
1661 if(!vm_customstats[i].type)
1663 switch(vm_customstats[i].type)
1665 //string as 16 bytes
1668 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1669 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1670 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1671 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1672 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1674 //float field sent as-is
1676 // can't directly use PRVM_E_INT on the field because it may be PRVM_64 and a double is not the representation we want to send
1677 u.f = PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1680 //integer value of float field
1682 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1690 // void(float index, float type, .void field) SV_AddStat = #232;
1691 // Set up an auto-sent player stat.
1692 // Client's get thier own fields sent to them. Index may not be less than 32.
1693 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1694 // 1: string (4 stats carrying a total of 16 charactures)
1695 // 2: float (one stat, float converted to an integer for transportation)
1696 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1697 static void VM_SV_AddStat(prvm_prog_t *prog)
1702 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1706 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1709 VM_Warning(prog, "PF_SV_AddStat: not enough memory\n");
1713 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1714 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1715 off = PRVM_G_INT (OFS_PARM2);
1720 VM_Warning(prog, "PF_SV_AddStat: index may not be less than 32\n");
1723 if(i >= (MAX_CL_STATS-32))
1725 VM_Warning(prog, "PF_SV_AddStat: index >= MAX_CL_STATS\n");
1728 if(i > (MAX_CL_STATS-32-4) && type == 1)
1730 VM_Warning(prog, "PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1733 vm_customstats[i].type = type;
1734 vm_customstats[i].fieldoffset = off;
1735 if(vm_customstats_last < i)
1736 vm_customstats_last = i;
1743 copies data from one entity to another
1745 copyentity(src, dst)
1748 static void VM_SV_copyentity(prvm_prog_t *prog)
1750 prvm_edict_t *in, *out;
1751 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1752 in = PRVM_G_EDICT(OFS_PARM0);
1753 if (in == prog->edicts)
1755 VM_Warning(prog, "copyentity: can not read world entity\n");
1758 if (in->priv.server->free)
1760 VM_Warning(prog, "copyentity: can not read free entity\n");
1763 out = PRVM_G_EDICT(OFS_PARM1);
1764 if (out == prog->edicts)
1766 VM_Warning(prog, "copyentity: can not modify world entity\n");
1769 if (out->priv.server->free)
1771 VM_Warning(prog, "copyentity: can not modify free entity\n");
1774 memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
1775 if (VectorCompare(PRVM_serveredictvector(out, absmin), PRVM_serveredictvector(out, absmax)))
1785 sets the color of a client and broadcasts the update to all connected clients
1787 setcolor(clientent, value)
1790 static void VM_SV_setcolor(prvm_prog_t *prog)
1795 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1796 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1797 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1799 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1801 Con_Print("tried to setcolor a non-client\n");
1805 client = svs.clients + entnum-1;
1808 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1809 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1812 if (client->old_colors != client->colors)
1814 client->old_colors = client->colors;
1815 // send notification to all clients
1816 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1817 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1818 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1826 effect(origin, modelname, startframe, framecount, framerate)
1829 static void VM_SV_effect(prvm_prog_t *prog)
1834 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1835 s = PRVM_G_STRING(OFS_PARM1);
1838 VM_Warning(prog, "effect: no model specified\n");
1842 i = SV_ModelIndex(s, 1);
1845 VM_Warning(prog, "effect: model not precached\n");
1849 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1851 VM_Warning(prog, "effect: framecount < 1\n");
1855 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1857 VM_Warning(prog, "effect: framerate < 1\n");
1861 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1862 SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1865 static void VM_SV_te_blood(prvm_prog_t *prog)
1867 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1868 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1870 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1871 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1873 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1874 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1875 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1877 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1878 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1879 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1881 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1882 SV_FlushBroadcastMessages();
1885 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1887 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1888 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1890 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1891 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1893 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1894 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1895 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1903 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1904 SV_FlushBroadcastMessages();
1907 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1909 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1910 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1911 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1913 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1914 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1915 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1917 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1918 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1919 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1920 SV_FlushBroadcastMessages();
1923 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1925 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1926 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1928 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1929 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1936 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1941 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1943 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1945 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1946 // gravity true/false
1947 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1949 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1950 SV_FlushBroadcastMessages();
1953 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1955 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1956 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1958 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1959 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1965 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1970 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1973 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1975 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1976 SV_FlushBroadcastMessages();
1979 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1981 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1982 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1984 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1985 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1989 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1991 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1992 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1993 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1995 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1996 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1997 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1999 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2001 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2002 SV_FlushBroadcastMessages();
2005 static void VM_SV_te_spark(prvm_prog_t *prog)
2007 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
2008 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2010 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2011 MSG_WriteByte(&sv.datagram, TE_SPARK);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2014 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2015 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2017 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2018 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2019 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2021 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2022 SV_FlushBroadcastMessages();
2025 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2027 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2028 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2029 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2031 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2032 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2033 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2034 SV_FlushBroadcastMessages();
2037 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2039 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2040 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2041 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2043 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2044 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2045 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2046 SV_FlushBroadcastMessages();
2049 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2051 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2052 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2053 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2055 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2056 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2058 SV_FlushBroadcastMessages();
2061 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2063 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2064 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2065 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2067 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2068 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2069 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2070 SV_FlushBroadcastMessages();
2073 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2075 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2076 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2077 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2079 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2080 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2081 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2082 SV_FlushBroadcastMessages();
2085 static void VM_SV_te_customflash(prvm_prog_t *prog)
2087 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2088 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2090 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2091 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2093 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2094 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2095 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2097 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2099 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2101 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2102 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2103 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2104 SV_FlushBroadcastMessages();
2107 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2109 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2110 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2111 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2113 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2114 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2115 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2116 SV_FlushBroadcastMessages();
2119 static void VM_SV_te_spike(prvm_prog_t *prog)
2121 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2122 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2123 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2125 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2126 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2127 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2128 SV_FlushBroadcastMessages();
2131 static void VM_SV_te_superspike(prvm_prog_t *prog)
2133 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2134 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2135 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2137 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2138 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2139 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2140 SV_FlushBroadcastMessages();
2143 static void VM_SV_te_explosion(prvm_prog_t *prog)
2145 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2146 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2147 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2149 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2150 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2151 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2152 SV_FlushBroadcastMessages();
2155 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2157 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2158 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2159 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2161 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2162 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2163 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2164 SV_FlushBroadcastMessages();
2167 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2169 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2170 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2171 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2173 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2174 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2175 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2176 SV_FlushBroadcastMessages();
2179 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2181 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2182 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2183 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2185 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2186 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2187 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2188 SV_FlushBroadcastMessages();
2191 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2193 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2194 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2195 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2197 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2198 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2199 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2200 SV_FlushBroadcastMessages();
2203 static void VM_SV_te_teleport(prvm_prog_t *prog)
2205 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2206 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2207 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2209 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2210 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2211 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2212 SV_FlushBroadcastMessages();
2215 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2217 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2218 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2219 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2221 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2222 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2223 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2225 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2226 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2227 SV_FlushBroadcastMessages();
2230 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2232 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2233 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2234 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2236 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2238 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2239 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2240 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2242 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2243 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2244 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2245 SV_FlushBroadcastMessages();
2248 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2250 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2251 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2252 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2254 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2256 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2257 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2258 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2260 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2261 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2262 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2263 SV_FlushBroadcastMessages();
2266 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2268 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2269 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2270 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2272 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2274 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2275 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2276 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2278 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2279 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2280 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2281 SV_FlushBroadcastMessages();
2284 static void VM_SV_te_beam(prvm_prog_t *prog)
2286 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2287 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2288 MSG_WriteByte(&sv.datagram, TE_BEAM);
2290 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2292 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2293 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2294 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2296 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2297 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2298 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2299 SV_FlushBroadcastMessages();
2302 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2304 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2305 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2306 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2307 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2308 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2309 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2310 SV_FlushBroadcastMessages();
2313 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2315 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2316 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2317 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2319 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2320 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2321 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2323 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2324 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2325 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2327 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2328 SV_FlushBroadcastMessages();
2331 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2332 //this function originally written by KrimZon, made shorter by LordHavoc
2333 static void VM_SV_clientcommand(prvm_prog_t *prog)
2335 client_t *temp_client;
2337 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2339 //find client for this entity
2340 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2341 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2343 Con_Print("PF_clientcommand: entity is not a client\n");
2347 temp_client = host_client;
2348 host_client = svs.clients + i;
2349 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
2350 host_client = temp_client;
2353 //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)
2354 static void VM_SV_setattachment(prvm_prog_t *prog)
2356 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2357 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2358 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2361 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2363 if (e == prog->edicts)
2365 VM_Warning(prog, "setattachment: can not modify world entity\n");
2368 if (e->priv.server->free)
2370 VM_Warning(prog, "setattachment: can not modify free entity\n");
2374 if (tagentity == NULL)
2375 tagentity = prog->edicts;
2379 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2381 model = SV_GetModelFromEdict(tagentity);
2384 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2386 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);
2389 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));
2392 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2393 PRVM_serveredictfloat(e, tag_index) = tagindex;
2396 /////////////////////////////////////////
2397 // DP_MD3_TAGINFO extension coded by VorteX
2399 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2403 i = (int)PRVM_serveredictfloat(e, modelindex);
2404 if (i < 1 || i >= MAX_MODELS)
2407 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2410 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2417 Matrix4x4_CreateIdentity(tag_localmatrix);
2419 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2421 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2432 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2435 float pitchsign = 1;
2437 scale = PRVM_serveredictfloat(ent, scale);
2442 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);
2445 pitchsign = SV_GetPitchSign(prog, ent);
2446 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);
2450 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2453 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2455 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2456 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2457 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2458 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2460 *out = identitymatrix;
2464 // Warnings/errors code:
2465 // 0 - normal (everything all-right)
2468 // 3 - null or non-precached model
2469 // 4 - no tags with requested index
2470 // 5 - runaway loop at attachment chain
2471 extern cvar_t cl_bob;
2472 extern cvar_t cl_bobcycle;
2473 extern cvar_t cl_bobup;
2474 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2477 int modelindex, attachloop;
2478 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2481 *out = identitymatrix; // warnings and errors return identical matrix
2483 if (ent == prog->edicts)
2485 if (ent->priv.server->free)
2488 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2489 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2492 model = SV_GetModelByIndex(modelindex);
2494 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2495 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2496 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2498 tagmatrix = identitymatrix;
2499 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2503 if (attachloop >= 256) // prevent runaway looping
2505 // apply transformation by child's tagindex on parent entity and then
2506 // by parent entity itself
2507 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2508 if (ret && attachloop == 0)
2510 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2511 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2512 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2513 // next iteration we process the parent entity
2514 if (PRVM_serveredictedict(ent, tag_entity))
2516 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2517 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2524 // RENDER_VIEWMODEL magic
2525 if (PRVM_serveredictedict(ent, viewmodelforclient))
2527 Matrix4x4_Copy(&tagmatrix, out);
2528 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2530 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2531 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2534 // Cl_bob, ported from rendering code
2535 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2538 // LordHavoc: this code is *weird*, but not replacable (I think it
2539 // should be done in QC on the server, but oh well, quake is quake)
2540 // LordHavoc: figured out bobup: the time at which the sin is at 180
2541 // degrees (which allows lengthening or squishing the peak or valley)
2542 cycle = sv.time/cl_bobcycle.value;
2543 cycle -= (int)cycle;
2544 if (cycle < cl_bobup.value)
2545 cycle = sin(M_PI * cycle / cl_bobup.value);
2547 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2548 // bob is proportional to velocity in the xy plane
2549 // (don't count Z, or jumping messes it up)
2550 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;
2551 bob = bob*0.3 + bob*0.7*cycle;
2552 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2559 //float(entity ent, string tagname) gettagindex;
2561 static void VM_SV_gettagindex(prvm_prog_t *prog)
2564 const char *tag_name;
2567 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2569 ent = PRVM_G_EDICT(OFS_PARM0);
2570 tag_name = PRVM_G_STRING(OFS_PARM1);
2572 if (ent == prog->edicts)
2574 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2577 if (ent->priv.server->free)
2579 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2584 if (!SV_GetModelFromEdict(ent))
2585 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2588 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2590 if(developer_extra.integer)
2591 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2593 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2596 //vector(entity ent, float tagindex) gettaginfo;
2597 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2601 matrix4x4_t tag_matrix;
2602 matrix4x4_t tag_localmatrix;
2604 const char *tagname;
2606 vec3_t forward, left, up, origin;
2607 const dp_model_t *model;
2609 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2611 e = PRVM_G_EDICT(OFS_PARM0);
2612 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2614 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2615 Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
2616 VectorCopy(forward, PRVM_serverglobalvector(v_forward));
2617 VectorNegate(left, PRVM_serverglobalvector(v_right));
2618 VectorCopy(up, PRVM_serverglobalvector(v_up));
2619 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2620 model = SV_GetModelFromEdict(e);
2621 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2622 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2623 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2624 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2625 Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
2627 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2628 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2629 VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
2630 VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
2631 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2632 VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset));
2637 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2640 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2643 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2646 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2649 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2654 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2655 static void VM_SV_dropclient(prvm_prog_t *prog)
2658 client_t *oldhostclient;
2659 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2660 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2661 if (clientnum < 0 || clientnum >= svs.maxclients)
2663 VM_Warning(prog, "dropclient: not a client\n");
2666 if (!svs.clients[clientnum].active)
2668 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2671 oldhostclient = host_client;
2672 host_client = svs.clients + clientnum;
2673 SV_DropClient(false);
2674 host_client = oldhostclient;
2677 //entity() spawnclient (DP_SV_BOTCLIENT)
2678 static void VM_SV_spawnclient(prvm_prog_t *prog)
2682 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2683 prog->xfunction->builtinsprofile += 2;
2685 for (i = 0;i < svs.maxclients;i++)
2687 if (!svs.clients[i].active)
2689 prog->xfunction->builtinsprofile += 100;
2690 SV_ConnectClient (i, NULL);
2691 // this has to be set or else ClientDisconnect won't be called
2692 // we assume the qc will call ClientConnect...
2693 svs.clients[i].clientconnectcalled = true;
2694 ed = PRVM_EDICT_NUM(i + 1);
2698 VM_RETURN_EDICT(ed);
2701 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2702 static void VM_SV_clienttype(prvm_prog_t *prog)
2705 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2706 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2707 if (clientnum < 0 || clientnum >= svs.maxclients)
2708 PRVM_G_FLOAT(OFS_RETURN) = 3;
2709 else if (!svs.clients[clientnum].active)
2710 PRVM_G_FLOAT(OFS_RETURN) = 0;
2711 else if (svs.clients[clientnum].netconnection)
2712 PRVM_G_FLOAT(OFS_RETURN) = 1;
2714 PRVM_G_FLOAT(OFS_RETURN) = 2;
2721 string(string key) serverkey
2724 static void VM_SV_serverkey(prvm_prog_t *prog)
2726 char string[VM_STRINGTEMP_LENGTH];
2727 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2728 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2729 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2732 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2733 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2738 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2740 e = PRVM_G_EDICT(OFS_PARM0);
2741 if (e == prog->edicts)
2743 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2746 if (e->priv.server->free)
2748 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2751 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2752 if (i <= 0 || i >= MAX_MODELS)
2754 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2757 if (!sv.model_precache[i][0])
2759 VM_Warning(prog, "setmodelindex: model not precached\n");
2763 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2764 PRVM_serveredictfloat(e, modelindex) = i;
2766 mod = SV_GetModelByIndex(i);
2770 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2771 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2773 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2776 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2779 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2780 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2783 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2785 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2787 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2788 if (i <= 0 || i >= MAX_MODELS)
2790 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2793 if (!sv.model_precache[i][0])
2795 VM_Warning(prog, "modelnameforindex: model not precached\n");
2799 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2802 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2803 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2806 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2807 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2810 PRVM_G_FLOAT(OFS_RETURN) = i;
2813 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2814 static void VM_SV_trailparticles(prvm_prog_t *prog)
2817 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2819 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2822 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2823 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2824 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2825 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start);
2826 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end);
2827 MSG_WriteVector(&sv.datagram, start, sv.protocol);
2828 MSG_WriteVector(&sv.datagram, end, sv.protocol);
2829 SV_FlushBroadcastMessages();
2832 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2833 static void VM_SV_pointparticles(prvm_prog_t *prog)
2835 int effectnum, count;
2837 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2839 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2842 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2843 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2844 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2845 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2846 if (count == 1 && !VectorLength2(vel))
2849 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2850 MSG_WriteShort(&sv.datagram, effectnum);
2851 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2855 // 1+2+12+12+2=29 bytes
2856 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2857 MSG_WriteShort(&sv.datagram, effectnum);
2858 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2859 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2860 MSG_WriteShort(&sv.datagram, count);
2863 SV_FlushBroadcastMessages();
2866 //PF_setpause, // void(float pause) setpause = #531;
2867 static void VM_SV_setpause(prvm_prog_t *prog) {
2869 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2870 if (pauseValue != 0) { //pause the game
2872 sv.pausedstart = realtime;
2873 } else { //disable pause, in case it was enabled
2874 if (sv.paused != 0) {
2879 // send notification to all clients
2880 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2881 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2884 // #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.
2885 static void VM_SV_skel_create(prvm_prog_t *prog)
2887 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2888 dp_model_t *model = SV_GetModelByIndex(modelindex);
2889 skeleton_t *skeleton;
2891 PRVM_G_FLOAT(OFS_RETURN) = 0;
2892 if (!model || !model->num_bones)
2894 for (i = 0;i < MAX_EDICTS;i++)
2895 if (!prog->skeletons[i])
2897 if (i == MAX_EDICTS)
2899 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(prog->progs_mempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2900 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2901 skeleton->model = model;
2902 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2903 // initialize to identity matrices
2904 for (i = 0;i < skeleton->model->num_bones;i++)
2905 skeleton->relativetransforms[i] = identitymatrix;
2908 // #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
2909 static void VM_SV_skel_build(prvm_prog_t *prog)
2911 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2912 skeleton_t *skeleton;
2913 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2914 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2915 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2916 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2917 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2918 dp_model_t *model = SV_GetModelByIndex(modelindex);
2922 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2923 frameblend_t frameblend[MAX_FRAMEBLENDS];
2924 matrix4x4_t bonematrix;
2926 PRVM_G_FLOAT(OFS_RETURN) = 0;
2927 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2929 firstbone = max(0, firstbone);
2930 lastbone = min(lastbone, model->num_bones - 1);
2931 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2932 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2933 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time);
2934 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2936 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2938 memset(&bonematrix, 0, sizeof(bonematrix));
2939 for (blendindex = 0;blendindex < numblends;blendindex++)
2941 Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2942 Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp);
2944 Matrix4x4_Normalize3(&bonematrix, &bonematrix);
2945 Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac);
2947 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2950 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2951 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
2953 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2954 skeleton_t *skeleton;
2955 PRVM_G_FLOAT(OFS_RETURN) = 0;
2956 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2958 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2961 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2962 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
2964 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2965 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2966 skeleton_t *skeleton;
2967 PRVM_G_INT(OFS_RETURN) = 0;
2968 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2970 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2972 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
2975 // #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)
2976 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
2978 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2979 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2980 skeleton_t *skeleton;
2981 PRVM_G_FLOAT(OFS_RETURN) = 0;
2982 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2984 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2986 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2989 // #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
2990 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
2992 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2993 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2994 skeleton_t *skeleton;
2995 PRVM_G_FLOAT(OFS_RETURN) = 0;
2996 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2998 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
3001 // #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)
3002 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
3004 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3005 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3006 skeleton_t *skeleton;
3008 vec3_t forward, left, up, origin;
3009 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3010 VectorClear(PRVM_clientglobalvector(v_forward));
3011 VectorClear(PRVM_clientglobalvector(v_right));
3012 VectorClear(PRVM_clientglobalvector(v_up));
3013 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3015 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3017 matrix = skeleton->relativetransforms[bonenum];
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 // #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)
3026 static void VM_SV_skel_get_boneabs(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 skeleton_t *skeleton;
3033 vec3_t forward, left, up, origin;
3034 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3035 VectorClear(PRVM_clientglobalvector(v_forward));
3036 VectorClear(PRVM_clientglobalvector(v_right));
3037 VectorClear(PRVM_clientglobalvector(v_up));
3038 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3040 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3042 matrix = skeleton->relativetransforms[bonenum];
3043 // convert to absolute
3044 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3047 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3049 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3050 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3051 VectorNegate(left, PRVM_clientglobalvector(v_right));
3052 VectorCopy(up, PRVM_clientglobalvector(v_up));
3053 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3056 // #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)
3057 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3059 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3060 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3061 vec3_t forward, left, up, origin;
3062 skeleton_t *skeleton;
3064 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3066 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3068 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3069 VectorNegate(PRVM_clientglobalvector(v_right), left);
3070 VectorCopy(PRVM_clientglobalvector(v_up), up);
3071 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3072 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3073 skeleton->relativetransforms[bonenum] = matrix;
3076 // #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)
3077 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3079 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3080 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3081 vec3_t forward, left, up, origin;
3082 skeleton_t *skeleton;
3085 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3087 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3089 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3090 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3091 VectorNegate(PRVM_clientglobalvector(v_right), left);
3092 VectorCopy(PRVM_clientglobalvector(v_up), up);
3093 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3094 temp = skeleton->relativetransforms[bonenum];
3095 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3098 // #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)
3099 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3101 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3102 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3103 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3105 vec3_t forward, left, up, origin;
3106 skeleton_t *skeleton;
3109 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3111 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3112 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3113 VectorNegate(PRVM_clientglobalvector(v_right), left);
3114 VectorCopy(PRVM_clientglobalvector(v_up), up);
3115 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3116 firstbone = max(0, firstbone);
3117 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3118 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3120 temp = skeleton->relativetransforms[bonenum];
3121 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3125 // #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
3126 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3128 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3129 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3130 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3131 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3133 skeleton_t *skeletondst;
3134 skeleton_t *skeletonsrc;
3135 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3137 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3139 firstbone = max(0, firstbone);
3140 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3141 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3142 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3143 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3146 // #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)
3147 static void VM_SV_skel_delete(prvm_prog_t *prog)
3149 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3150 skeleton_t *skeleton;
3151 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3154 prog->skeletons[skeletonindex] = NULL;
3157 // #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
3158 static void VM_SV_frameforname(prvm_prog_t *prog)
3160 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3161 dp_model_t *model = SV_GetModelByIndex(modelindex);
3162 const char *name = PRVM_G_STRING(OFS_PARM1);
3164 PRVM_G_FLOAT(OFS_RETURN) = -1;
3165 if (!model || !model->animscenes)
3167 for (i = 0;i < model->numframes;i++)
3169 if (!strcasecmp(model->animscenes[i].name, name))
3171 PRVM_G_FLOAT(OFS_RETURN) = i;
3177 // #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.
3178 static void VM_SV_frameduration(prvm_prog_t *prog)
3180 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3181 dp_model_t *model = SV_GetModelByIndex(modelindex);
3182 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3183 PRVM_G_FLOAT(OFS_RETURN) = 0;
3184 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3186 if (model->animscenes[framenum].framerate)
3187 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3191 prvm_builtin_t vm_sv_builtins[] = {
3192 NULL, // #0 NULL function (not callable) (QUAKE)
3193 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3194 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3195 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3196 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3197 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3198 VM_break, // #6 void() break (QUAKE)
3199 VM_random, // #7 float() random (QUAKE)
3200 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3201 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3202 VM_error, // #10 void(string e) error (QUAKE)
3203 VM_objerror, // #11 void(string e) objerror (QUAKE)
3204 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3205 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3206 VM_spawn, // #14 entity() spawn (QUAKE)
3207 VM_remove, // #15 void(entity e) remove (QUAKE)
3208 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3209 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3210 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3211 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3212 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3213 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3214 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3215 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3216 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3217 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3218 VM_ftos, // #26 string(float f) ftos (QUAKE)
3219 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3220 VM_coredump, // #28 void() coredump (QUAKE)
3221 VM_traceon, // #29 void() traceon (QUAKE)
3222 VM_traceoff, // #30 void() traceoff (QUAKE)
3223 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3224 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3225 NULL, // #33 (QUAKE)
3226 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3227 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3228 VM_rint, // #36 float(float v) rint (QUAKE)
3229 VM_floor, // #37 float(float v) floor (QUAKE)
3230 VM_ceil, // #38 float(float v) ceil (QUAKE)
3231 NULL, // #39 (QUAKE)
3232 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3233 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3234 NULL, // #42 (QUAKE)
3235 VM_fabs, // #43 float(float f) fabs (QUAKE)
3236 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3237 VM_cvar, // #45 float(string s) cvar (QUAKE)
3238 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3239 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3240 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3241 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3242 NULL, // #50 (QUAKE)
3243 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3244 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3245 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3246 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3247 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3248 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3249 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3250 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3251 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3252 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3253 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3254 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3255 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3256 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3257 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3258 NULL, // #66 (QUAKE)
3259 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3260 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3261 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3262 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3263 NULL, // #71 (QUAKE)
3264 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3265 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3266 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3267 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3268 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3269 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3270 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3271 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3272 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3273 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3274 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3275 NULL, // #83 (QUAKE)
3276 NULL, // #84 (QUAKE)
3277 NULL, // #85 (QUAKE)
3278 NULL, // #86 (QUAKE)
3279 NULL, // #87 (QUAKE)
3280 NULL, // #88 (QUAKE)
3281 NULL, // #89 (QUAKE)
3282 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3283 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3284 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3285 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3286 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3287 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3288 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3289 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3290 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3291 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3292 // FrikaC and Telejano range #100-#199
3303 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3304 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3305 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3306 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3307 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3308 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3309 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3310 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3311 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3312 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3393 // FTEQW range #200-#299
3412 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3415 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3416 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3417 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3418 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3419 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3420 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3421 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3422 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3423 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3424 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3426 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3434 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3457 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.
3458 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
3459 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3460 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3461 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)
3462 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
3463 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)
3464 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)
3465 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)
3466 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)
3467 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)
3468 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
3469 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)
3470 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
3471 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.
3494 // CSQC range #300-#399
3495 NULL, // #300 void() clearscene (EXT_CSQC)
3496 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3497 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3498 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3499 NULL, // #304 void() renderscene (EXT_CSQC)
3500 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3501 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3502 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3503 NULL, // #308 void() R_EndPolygon
3505 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3506 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3510 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3511 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3512 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3513 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3514 NULL, // #319 void(string name) freepic (EXT_CSQC)
3515 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3516 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3517 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3518 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3519 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3520 NULL, // #325 void(void) drawresetcliparea
3525 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3526 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3527 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3528 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3529 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3530 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3531 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3532 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3533 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3534 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3535 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3536 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3537 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3538 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3539 NULL, // #344 vector() getmousepos (EXT_CSQC)
3540 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3541 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3542 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3543 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3544 NULL, // #349 float() isdemo (EXT_CSQC)
3545 VM_isserver, // #350 float() isserver (EXT_CSQC)
3546 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3547 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3548 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3549 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3555 NULL, // #360 float() readbyte (EXT_CSQC)
3556 NULL, // #361 float() readchar (EXT_CSQC)
3557 NULL, // #362 float() readshort (EXT_CSQC)
3558 NULL, // #363 float() readlong (EXT_CSQC)
3559 NULL, // #364 float() readcoord (EXT_CSQC)
3560 NULL, // #365 float() readangle (EXT_CSQC)
3561 NULL, // #366 string() readstring (EXT_CSQC)
3562 NULL, // #367 float() readfloat (EXT_CSQC)
3595 // LordHavoc's range #400-#499
3596 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3597 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3598 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3599 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3600 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3601 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3602 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3603 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3604 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)
3605 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3606 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3607 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3608 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3609 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3610 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3611 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3612 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3613 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3614 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3615 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3616 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3617 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3618 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3619 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3620 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3621 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3622 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3623 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3624 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3625 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3626 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3627 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3628 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3629 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3630 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3631 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3632 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3633 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3634 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3635 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3636 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3637 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3638 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3639 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3640 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3641 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3642 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3643 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3644 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3645 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3646 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3647 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3648 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3649 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3650 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3651 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3652 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3653 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3655 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3656 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3657 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3658 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3659 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3660 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3661 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3662 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3663 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3664 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3665 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3667 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3668 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3669 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3670 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3671 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3672 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3673 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3674 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3675 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3676 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3677 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3678 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3679 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3680 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3681 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3682 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3690 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3691 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3692 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3693 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3694 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3695 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3696 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3697 VM_SV_WritePicture, // #501
3699 VM_whichpack, // #503 string(string) whichpack = #503;
3706 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3707 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3708 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3709 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)
3710 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3711 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3712 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3713 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3714 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3715 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3725 VM_loadfromdata, // #529
3726 VM_loadfromfile, // #530
3727 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3729 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3730 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3731 VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP)
3732 VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP)
3733 VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP)
3734 VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP)
3736 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3737 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3738 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3801 VM_callfunction, // #605
3802 VM_writetofile, // #606
3803 VM_isfunction, // #607
3809 VM_parseentitydata, // #613
3820 VM_SV_getextresponse, // #624 string getextresponse(void)
3823 VM_sprintf, // #627 string sprintf(string format, ...)
3824 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3825 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3835 VM_digest_hex, // #639
3838 VM_coverage, // #642
3842 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3844 void SVVM_init_cmd(prvm_prog_t *prog)
3849 void SVVM_reset_cmd(prvm_prog_t *prog)
3851 World_End(&sv.world);
3853 if(prog->loaded && PRVM_serverfunction(SV_Shutdown))
3855 func_t s = PRVM_serverfunction(SV_Shutdown);
3856 PRVM_serverglobalfloat(time) = sv.time;
3857 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3858 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");