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_DISCARDABLEDEMO "
172 "DP_SV_DRAWONLYTOCLIENT "
175 "DP_SV_ENTITYCONTENTSTRANSITION "
176 "DP_SV_MODELFLAGS_AS_EFFECTS "
177 "DP_SV_MOVETYPESTEP_LANDEVENT "
179 "DP_SV_NODRAWTOCLIENT "
180 "DP_SV_ONENTITYNOSPAWNFUNCTION "
181 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
183 "DP_SV_PING_PACKETLOSS "
184 "DP_SV_PLAYERPHYSICS "
186 "DP_SV_POINTPARTICLES "
188 "DP_SV_PRECACHEANYTIME "
192 "DP_SV_ROTATINGBMODEL "
196 "DP_SV_SPAWNFUNC_PREFIX "
197 "DP_SV_WRITEPICTURE "
198 "DP_SV_WRITEUNTERMINATEDSTRING "
202 "DP_TE_EXPLOSIONRGB "
204 "DP_TE_PARTICLECUBE "
205 "DP_TE_PARTICLERAIN "
206 "DP_TE_PARTICLESNOW "
208 "DP_TE_QUADEFFECTS1 "
211 "DP_TE_STANDARDEFFECTBUILTINS "
212 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
216 "FTE_CSQC_SKELETONOBJECTS "
219 "KRIMZON_SV_PARSECLIENTCOMMAND "
222 "NEXUIZ_PLAYERMODEL "
224 "PRYDON_CLIENTCURSOR "
225 "TENEBRAE_GFX_DLIGHTS "
228 //"EXT_CSQC " // not ready yet
235 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.
237 setorigin (entity, origin)
240 static void VM_SV_setorigin(prvm_prog_t *prog)
244 VM_SAFEPARMCOUNT(2, VM_setorigin);
246 e = PRVM_G_EDICT(OFS_PARM0);
247 if (e == prog->edicts)
249 VM_Warning(prog, "setorigin: can not modify world entity\n");
252 if (e->priv.server->free)
254 VM_Warning(prog, "setorigin: can not modify free entity\n");
257 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), PRVM_serveredictvector(e, origin));
258 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
259 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
263 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
264 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qboolean rotate)
268 for (i=0 ; i<3 ; i++)
270 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
272 // set derived values
273 VectorCopy (min, PRVM_serveredictvector(e, mins));
274 VectorCopy (max, PRVM_serveredictvector(e, maxs));
275 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
284 the size box is rotated by the current angle
285 LordHavoc: no it isn't...
287 setsize (entity, minvector, maxvector)
290 static void VM_SV_setsize(prvm_prog_t *prog)
295 VM_SAFEPARMCOUNT(3, VM_setsize);
297 e = PRVM_G_EDICT(OFS_PARM0);
298 if (e == prog->edicts)
300 VM_Warning(prog, "setsize: can not modify world entity\n");
303 if (e->priv.server->free)
305 VM_Warning(prog, "setsize: can not modify free entity\n");
308 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), mins);
309 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), maxs);
310 SetMinMaxSize(prog, e, mins, maxs, false);
318 setmodel(entity, model)
321 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
322 static void VM_SV_setmodel(prvm_prog_t *prog)
328 VM_SAFEPARMCOUNT(2, VM_setmodel);
330 e = PRVM_G_EDICT(OFS_PARM0);
331 if (e == prog->edicts)
333 VM_Warning(prog, "setmodel: can not modify world entity\n");
336 if (e->priv.server->free)
338 VM_Warning(prog, "setmodel: can not modify free entity\n");
341 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
342 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
343 PRVM_serveredictfloat(e, modelindex) = i;
345 mod = SV_GetModelByIndex(i);
349 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
350 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
352 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
355 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
362 single print to a specific client
364 sprint(clientent, value)
367 static void VM_SV_sprint(prvm_prog_t *prog)
371 char string[VM_STRINGTEMP_LENGTH];
373 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
375 VM_VarString(prog, 1, string, sizeof(string));
377 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
378 // LordHavoc: div0 requested that sprintto world operate like print
385 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
387 VM_Warning(prog, "tried to centerprint to a non-client\n");
391 client = svs.clients + entnum-1;
392 if (!client->netconnection)
395 MSG_WriteChar(&client->netconnection->message,svc_print);
396 MSG_WriteString(&client->netconnection->message, string);
404 single print to a specific client
406 centerprint(clientent, value)
409 static void VM_SV_centerprint(prvm_prog_t *prog)
413 char string[VM_STRINGTEMP_LENGTH];
415 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
417 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
419 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
421 VM_Warning(prog, "tried to centerprint to a non-client\n");
425 client = svs.clients + entnum-1;
426 if (!client->netconnection)
429 VM_VarString(prog, 1, string, sizeof(string));
430 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
431 MSG_WriteString(&client->netconnection->message, string);
438 particle(origin, color, count)
441 static void VM_SV_particle(prvm_prog_t *prog)
447 VM_SAFEPARMCOUNT(4, VM_SV_particle);
449 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
450 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
451 color = (int)PRVM_G_FLOAT(OFS_PARM2);
452 count = (int)PRVM_G_FLOAT(OFS_PARM3);
453 SV_StartParticle (org, dir, color, count);
463 static void VM_SV_ambientsound(prvm_prog_t *prog)
467 prvm_vec_t vol, attenuation;
470 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
472 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
473 samp = PRVM_G_STRING(OFS_PARM1);
474 vol = PRVM_G_FLOAT(OFS_PARM2);
475 attenuation = PRVM_G_FLOAT(OFS_PARM3);
477 // check to see if samp was properly precached
478 soundnum = SV_SoundIndex(samp, 1);
486 // add an svc_spawnambient command to the level signon packet
489 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
491 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
493 MSG_WriteVector(&sv.signon, pos, sv.protocol);
495 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
496 MSG_WriteShort (&sv.signon, soundnum);
498 MSG_WriteByte (&sv.signon, soundnum);
500 MSG_WriteByte (&sv.signon, (int)(vol*255));
501 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
509 Each entity can have eight independant sound sources, like voice,
512 Channel 0 is an auto-allocate channel, the others override anything
513 already running on that entity/channel pair.
515 An attenuation of 0 will play full volume everywhere in the level.
516 Larger attenuations will drop off.
520 static void VM_SV_sound(prvm_prog_t *prog)
524 prvm_edict_t *entity;
530 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
532 entity = PRVM_G_EDICT(OFS_PARM0);
533 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
534 sample = PRVM_G_STRING(OFS_PARM2);
535 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
538 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
542 attenuation = PRVM_G_FLOAT(OFS_PARM4);
546 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
551 if(channel >= 8 && channel <= 15) // weird QW feature
553 flags |= CHANNELFLAG_RELIABLE;
559 // LordHavoc: we only let the qc set certain flags, others are off-limits
560 flags = (int)PRVM_G_FLOAT(OFS_PARM6) & (CHANNELFLAG_RELIABLE | CHANNELFLAG_FORCELOOP | CHANNELFLAG_PAUSED);
563 if (volume < 0 || volume > 255)
565 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
569 if (attenuation < 0 || attenuation > 4)
571 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
575 channel = CHAN_USER2ENGINE(channel);
577 if (!IS_CHAN(channel))
579 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
583 SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANNELFLAG_RELIABLE, pitchchange);
590 Follows the same logic as VM_SV_sound, except instead of
591 an entity, an origin for the sound is provided, and channel
592 is omitted (since no entity is being tracked).
596 static void VM_SV_pointsound(prvm_prog_t *prog)
604 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
606 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
607 sample = PRVM_G_STRING(OFS_PARM1);
608 volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
609 attenuation = PRVM_G_FLOAT(OFS_PARM3);
610 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
612 if (volume < 0 || volume > 255)
614 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
618 if (attenuation < 0 || attenuation > 4)
620 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
624 SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
631 Used for use tracing and shot targeting
632 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
633 if the tryents flag is set.
635 traceline (vector1, vector2, movetype, ignore)
638 static void VM_SV_traceline(prvm_prog_t *prog)
645 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
647 prog->xfunction->builtinsprofile += 30;
649 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
650 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), v2);
651 move = (int)PRVM_G_FLOAT(OFS_PARM2);
652 ent = PRVM_G_EDICT(OFS_PARM3);
654 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]))
655 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));
657 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent), collision_extendtracelinelength.value);
659 VM_SetTraceGlobals(prog, &trace);
667 Used for use tracing and shot targeting
668 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
669 if the tryents flag is set.
671 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
674 // LordHavoc: added this for my own use, VERY useful, similar to traceline
675 static void VM_SV_tracebox(prvm_prog_t *prog)
677 vec3_t v1, v2, m1, m2;
682 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
684 prog->xfunction->builtinsprofile += 30;
686 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
687 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), m1);
688 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), m2);
689 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), v2);
690 move = (int)PRVM_G_FLOAT(OFS_PARM4);
691 ent = PRVM_G_EDICT(OFS_PARM5);
693 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]))
694 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));
696 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent), collision_extendtraceboxlength.value);
698 VM_SetTraceGlobals(prog, &trace);
701 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
705 vec3_t move, end, tossentorigin, tossentmins, tossentmaxs;
706 vec3_t original_origin;
707 vec3_t original_velocity;
708 vec3_t original_angles;
709 vec3_t original_avelocity;
712 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
713 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
714 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
715 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
717 gravity = PRVM_serveredictfloat(tossent, gravity);
720 gravity *= sv_gravity.value * 0.025;
722 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
724 SV_CheckVelocity (tossent);
725 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
726 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
727 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
728 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
729 VectorCopy(PRVM_serveredictvector(tossent, origin), tossentorigin);
730 VectorCopy(PRVM_serveredictvector(tossent, mins), tossentmins);
731 VectorCopy(PRVM_serveredictvector(tossent, maxs), tossentmaxs);
732 trace = SV_TraceBox(tossentorigin, tossentmins, tossentmaxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent), collision_extendmovelength.value);
733 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
734 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
736 if (trace.fraction < 1)
740 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
741 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
742 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
743 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
748 static void VM_SV_tracetoss(prvm_prog_t *prog)
752 prvm_edict_t *ignore;
754 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
756 prog->xfunction->builtinsprofile += 600;
758 ent = PRVM_G_EDICT(OFS_PARM0);
759 if (ent == prog->edicts)
761 VM_Warning(prog, "tracetoss: can not use world entity\n");
764 ignore = PRVM_G_EDICT(OFS_PARM1);
766 trace = SV_Trace_Toss(prog, ent, ignore);
768 VM_SetTraceGlobals(prog, &trace);
771 //============================================================================
773 static int checkpvsbytes;
774 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
776 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
782 // cycle to the next one
784 check = bound(1, check, svs.maxclients);
785 if (check == svs.maxclients)
793 prog->xfunction->builtinsprofile++;
795 if (i == svs.maxclients+1)
797 // look up the client's edict
798 ent = PRVM_EDICT_NUM(i);
799 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
800 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
802 // found a valid client (possibly the same one again)
806 // get the PVS for the entity
807 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
809 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
810 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
819 Returns a client (or object that has a client enemy) that would be a
822 If there is more than one valid option, they are cycled each frame
824 If (self.origin + self.viewofs) is not in the PVS of the current target,
825 it is not returned at all.
830 int c_invis, c_notvis;
831 static void VM_SV_checkclient(prvm_prog_t *prog)
833 prvm_edict_t *ent, *self;
836 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
838 // find a new check if on a new frame
839 if (sv.time - sv.lastchecktime >= 0.1)
841 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
842 sv.lastchecktime = sv.time;
845 // return check if it might be visible
846 ent = PRVM_EDICT_NUM(sv.lastcheck);
847 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
849 VM_RETURN_EDICT(prog->edicts);
853 // if current entity can't possibly see the check entity, return 0
854 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
855 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
856 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
859 VM_RETURN_EDICT(prog->edicts);
863 // might be able to see it
865 VM_RETURN_EDICT(ent);
868 //============================================================================
874 Checks if an entity is in a point's PVS.
875 Should be fast but can be inexact.
877 float checkpvs(vector viewpos, entity viewee) = #240;
880 static void VM_SV_checkpvs(prvm_prog_t *prog)
882 vec3_t viewpos, absmin, absmax;
883 prvm_edict_t *viewee;
888 unsigned char fatpvs[MAX_MAP_LEAFS/8];
891 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
892 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
893 viewee = PRVM_G_EDICT(OFS_PARM1);
895 if(viewee->priv.server->free)
897 VM_Warning(prog, "checkpvs: can not check free entity\n");
898 PRVM_G_FLOAT(OFS_RETURN) = 4;
903 if(!sv.worldmodel || !sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
905 // no PVS support on this worldmodel... darn
906 PRVM_G_FLOAT(OFS_RETURN) = 3;
909 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
912 // viewpos isn't in any PVS... darn
913 PRVM_G_FLOAT(OFS_RETURN) = 2;
916 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
917 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
918 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, absmin, absmax);
920 // using fat PVS like FTEQW does (slow)
921 if(!sv.worldmodel || !sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
923 // no PVS support on this worldmodel... darn
924 PRVM_G_FLOAT(OFS_RETURN) = 3;
927 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
930 // viewpos isn't in any PVS... darn
931 PRVM_G_FLOAT(OFS_RETURN) = 2;
934 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
935 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
936 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, absmin, absmax);
945 Sends text over to the client's execution buffer
947 stuffcmd (clientent, value, ...)
950 static void VM_SV_stuffcmd(prvm_prog_t *prog)
954 char string[VM_STRINGTEMP_LENGTH];
956 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
958 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
959 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
961 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
965 VM_VarString(prog, 1, string, sizeof(string));
968 host_client = svs.clients + entnum-1;
969 Host_ClientCommands ("%s", string);
977 Returns a chain of entities that have origins within a spherical area
979 findradius (origin, radius)
982 static void VM_SV_findradius(prvm_prog_t *prog)
984 prvm_edict_t *ent, *chain;
985 vec_t radius, radius2;
986 vec3_t org, eorg, mins, maxs;
989 static prvm_edict_t *touchedicts[MAX_EDICTS];
992 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
995 chainfield = PRVM_G_INT(OFS_PARM2);
997 chainfield = prog->fieldoffsets.chain;
999 prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
1001 chain = (prvm_edict_t *)prog->edicts;
1003 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1004 radius = PRVM_G_FLOAT(OFS_PARM1);
1005 radius2 = radius * radius;
1007 mins[0] = org[0] - (radius + 1);
1008 mins[1] = org[1] - (radius + 1);
1009 mins[2] = org[2] - (radius + 1);
1010 maxs[0] = org[0] + (radius + 1);
1011 maxs[1] = org[1] + (radius + 1);
1012 maxs[2] = org[2] + (radius + 1);
1013 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1014 if (numtouchedicts > MAX_EDICTS)
1016 // this never happens
1017 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1018 numtouchedicts = MAX_EDICTS;
1020 for (i = 0;i < numtouchedicts;i++)
1022 ent = touchedicts[i];
1023 prog->xfunction->builtinsprofile++;
1024 // Quake did not return non-solid entities but darkplaces does
1025 // (note: this is the reason you can't blow up fallen zombies)
1026 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1028 // LordHavoc: compare against bounding box rather than center so it
1029 // doesn't miss large objects, and use DotProduct instead of Length
1030 // for a major speedup
1031 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1032 if (sv_gameplayfix_findradiusdistancetobox.integer)
1034 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1035 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1036 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1039 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1040 if (DotProduct(eorg, eorg) < radius2)
1042 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1047 VM_RETURN_EDICT(chain);
1050 static void VM_SV_precache_sound(prvm_prog_t *prog)
1052 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1053 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1056 static void VM_SV_precache_model(prvm_prog_t *prog)
1058 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1059 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1060 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1067 float(float yaw, float dist[, settrace]) walkmove
1070 static void VM_SV_walkmove(prvm_prog_t *prog)
1079 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1081 // assume failure if it returns early
1082 PRVM_G_FLOAT(OFS_RETURN) = 0;
1084 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1085 if (ent == prog->edicts)
1087 VM_Warning(prog, "walkmove: can not modify world entity\n");
1090 if (ent->priv.server->free)
1092 VM_Warning(prog, "walkmove: can not modify free entity\n");
1095 yaw = PRVM_G_FLOAT(OFS_PARM0);
1096 dist = PRVM_G_FLOAT(OFS_PARM1);
1097 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1099 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1102 yaw = yaw*M_PI*2 / 360;
1104 move[0] = cos(yaw)*dist;
1105 move[1] = sin(yaw)*dist;
1108 // save program state, because SV_movestep may call other progs
1109 oldf = prog->xfunction;
1110 oldself = PRVM_serverglobaledict(self);
1112 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1115 // restore program state
1116 prog->xfunction = oldf;
1117 PRVM_serverglobaledict(self) = oldself;
1128 static void VM_SV_droptofloor(prvm_prog_t *prog)
1131 vec3_t end, entorigin, entmins, entmaxs;
1134 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1136 // assume failure if it returns early
1137 PRVM_G_FLOAT(OFS_RETURN) = 0;
1139 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1140 if (ent == prog->edicts)
1142 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1145 if (ent->priv.server->free)
1147 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1151 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1154 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1155 SV_NudgeOutOfSolid(ent);
1157 VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
1158 VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
1159 VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
1160 trace = SV_TraceBox(entorigin, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), collision_extendmovelength.value);
1161 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1164 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]);
1165 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1166 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), collision_extendmovelength.value);
1167 VectorSubtract(trace.endpos, offset, trace.endpos);
1168 if (trace.startsolid)
1170 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]);
1172 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1173 PRVM_serveredictedict(ent, groundentity) = 0;
1174 PRVM_G_FLOAT(OFS_RETURN) = 1;
1176 else if (trace.fraction < 1)
1178 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]);
1179 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1180 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1181 SV_NudgeOutOfSolid(ent);
1183 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1184 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1185 PRVM_G_FLOAT(OFS_RETURN) = 1;
1186 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1187 ent->priv.server->suspendedinairflag = true;
1192 if (!trace.allsolid && trace.fraction < 1)
1194 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1196 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1197 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1198 PRVM_G_FLOAT(OFS_RETURN) = 1;
1199 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1200 ent->priv.server->suspendedinairflag = true;
1209 void(float style, string value) lightstyle
1212 static void VM_SV_lightstyle(prvm_prog_t *prog)
1219 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1221 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1222 val = PRVM_G_STRING(OFS_PARM1);
1224 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1225 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1228 // change the string in sv
1229 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1231 // send message to all clients on this server
1232 if (sv.state != ss_active)
1235 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1237 if (client->active && client->netconnection)
1239 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1240 MSG_WriteChar (&client->netconnection->message,style);
1241 MSG_WriteString (&client->netconnection->message, val);
1251 static void VM_SV_checkbottom(prvm_prog_t *prog)
1253 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1254 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1262 static void VM_SV_pointcontents(prvm_prog_t *prog)
1265 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1266 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point);
1267 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(point));
1274 Pick a vector for the player to shoot along
1275 vector aim(entity, missilespeed)
1278 static void VM_SV_aim(prvm_prog_t *prog)
1280 prvm_edict_t *ent, *check, *bestent;
1281 vec3_t start, dir, end, bestdir;
1284 float dist, bestdist;
1287 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1289 // assume failure if it returns early
1290 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1291 // if sv_aim is so high it can't possibly accept anything, skip out early
1292 if (sv_aim.value >= 1)
1295 ent = PRVM_G_EDICT(OFS_PARM0);
1296 if (ent == prog->edicts)
1298 VM_Warning(prog, "aim: can not use world entity\n");
1301 if (ent->priv.server->free)
1303 VM_Warning(prog, "aim: can not use free entity\n");
1306 //speed = PRVM_G_FLOAT(OFS_PARM1);
1308 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1311 // try sending a trace straight
1312 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1313 VectorMA (start, 2048, dir, end);
1314 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, collision_extendmovelength.value);
1315 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1316 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1318 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1323 // try all possible entities
1324 VectorCopy (dir, bestdir);
1325 bestdist = sv_aim.value;
1328 check = PRVM_NEXT_EDICT(prog->edicts);
1329 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1331 prog->xfunction->builtinsprofile++;
1332 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1336 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1337 continue; // don't aim at teammate
1338 for (j=0 ; j<3 ; j++)
1339 end[j] = PRVM_serveredictvector(check, origin)[j]
1340 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1341 VectorSubtract (end, start, dir);
1342 VectorNormalize (dir);
1343 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1344 if (dist < bestdist)
1345 continue; // to far to turn
1346 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, collision_extendmovelength.value);
1347 if (tr.ent == check)
1348 { // can shoot at this one
1356 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1357 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1358 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1360 VectorNormalize (end);
1361 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1365 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1370 ===============================================================================
1374 ===============================================================================
1377 #define MSG_BROADCAST 0 // unreliable to all
1378 #define MSG_ONE 1 // reliable to one (msg_entity)
1379 #define MSG_ALL 2 // reliable to all
1380 #define MSG_INIT 3 // write to the init string
1381 #define MSG_ENTITY 5
1383 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1389 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1393 return &sv.datagram;
1396 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1397 entnum = PRVM_NUM_FOR_EDICT(ent);
1398 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1400 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1401 return &sv.reliable_datagram;
1404 return &svs.clients[entnum-1].netconnection->message;
1407 VM_Warning(prog, "WriteDest: bad destination\n");
1409 return &sv.reliable_datagram;
1415 return sv.writeentitiestoclient_msg;
1421 static void VM_SV_WriteByte(prvm_prog_t *prog)
1423 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1424 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1427 static void VM_SV_WriteChar(prvm_prog_t *prog)
1429 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1430 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1433 static void VM_SV_WriteShort(prvm_prog_t *prog)
1435 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1436 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1439 static void VM_SV_WriteLong(prvm_prog_t *prog)
1441 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1442 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1445 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1447 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1448 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1451 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1453 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1454 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1457 static void VM_SV_WriteString(prvm_prog_t *prog)
1459 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1460 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1463 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1465 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1466 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1470 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1472 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1473 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1476 // writes a picture as at most size bytes of data
1478 // IMGNAME \0 SIZE(short) IMGDATA
1479 // if failed to read/compress:
1481 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1482 static void VM_SV_WritePicture(prvm_prog_t *prog)
1484 const char *imgname;
1488 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1490 imgname = PRVM_G_STRING(OFS_PARM1);
1491 size = (size_t) PRVM_G_FLOAT(OFS_PARM2);
1495 MSG_WriteString(WriteDest(prog), imgname);
1496 if(Image_Compress(imgname, size, &buf, &size))
1499 MSG_WriteShort(WriteDest(prog), (int)size);
1500 SZ_Write(WriteDest(prog), (unsigned char *) buf, (int)size);
1505 MSG_WriteShort(WriteDest(prog), 0);
1509 //////////////////////////////////////////////////////////
1511 static void VM_SV_makestatic(prvm_prog_t *prog)
1516 // allow 0 parameters due to an id1 qc bug in which this function is used
1517 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1518 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1520 if (prog->argc >= 1)
1521 ent = PRVM_G_EDICT(OFS_PARM0);
1523 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1524 if (ent == prog->edicts)
1526 VM_Warning(prog, "makestatic: can not modify world entity\n");
1529 if (ent->priv.server->free)
1531 VM_Warning(prog, "makestatic: can not modify free entity\n");
1536 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1541 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1542 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1543 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1545 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1547 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1548 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1549 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1553 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1554 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1555 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1558 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1559 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1560 for (i=0 ; i<3 ; i++)
1562 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1563 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1566 // throw the entity away now
1567 PRVM_ED_Free(prog, ent);
1570 //=============================================================================
1577 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1583 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1585 ent = PRVM_G_EDICT(OFS_PARM0);
1586 i = PRVM_NUM_FOR_EDICT(ent);
1587 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1589 Con_Print("tried to setspawnparms on a non-client\n");
1593 // copy spawn parms out of the client_t
1594 client = svs.clients + i-1;
1595 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1596 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1603 Returns a color vector indicating the lighting at the requested point.
1605 (Internal Operation note: actually measures the light beneath the point, just like
1606 the model lighting on the client)
1611 static void VM_SV_getlight(prvm_prog_t *prog)
1613 vec3_t ambientcolor, diffusecolor, diffusenormal;
1615 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1616 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
1617 VectorClear(ambientcolor);
1618 VectorClear(diffusecolor);
1619 VectorClear(diffusenormal);
1620 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1621 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1622 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1627 unsigned char type; // 1/2/8 or other value if isn't used
1631 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1632 static int vm_customstats_last;
1634 void VM_CustomStats_Clear (void)
1638 Z_Free(vm_customstats);
1639 vm_customstats = NULL;
1640 vm_customstats_last = -1;
1644 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1646 prvm_prog_t *prog = SVVM_prog;
1653 for(i=0; i<vm_customstats_last+1 ;i++)
1655 if(!vm_customstats[i].type)
1657 switch(vm_customstats[i].type)
1659 //string as 16 bytes
1662 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1663 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1664 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1665 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1666 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1668 //float field sent as-is
1670 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1672 //integer value of float field
1674 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1682 // void(float index, float type, .void field) SV_AddStat = #232;
1683 // Set up an auto-sent player stat.
1684 // Client's get thier own fields sent to them. Index may not be less than 32.
1685 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1686 // 1: string (4 stats carrying a total of 16 charactures)
1687 // 2: float (one stat, float converted to an integer for transportation)
1688 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1689 static void VM_SV_AddStat(prvm_prog_t *prog)
1694 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1698 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1701 VM_Warning(prog, "PF_SV_AddStat: not enough memory\n");
1705 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1706 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1707 off = PRVM_G_INT (OFS_PARM2);
1712 VM_Warning(prog, "PF_SV_AddStat: index may not be less than 32\n");
1715 if(i >= (MAX_CL_STATS-32))
1717 VM_Warning(prog, "PF_SV_AddStat: index >= MAX_CL_STATS\n");
1720 if(i > (MAX_CL_STATS-32-4) && type == 1)
1722 VM_Warning(prog, "PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1725 vm_customstats[i].type = type;
1726 vm_customstats[i].fieldoffset = off;
1727 if(vm_customstats_last < i)
1728 vm_customstats_last = i;
1735 copies data from one entity to another
1737 copyentity(src, dst)
1740 static void VM_SV_copyentity(prvm_prog_t *prog)
1742 prvm_edict_t *in, *out;
1743 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1744 in = PRVM_G_EDICT(OFS_PARM0);
1745 if (in == prog->edicts)
1747 VM_Warning(prog, "copyentity: can not read world entity\n");
1750 if (in->priv.server->free)
1752 VM_Warning(prog, "copyentity: can not read free entity\n");
1755 out = PRVM_G_EDICT(OFS_PARM1);
1756 if (out == prog->edicts)
1758 VM_Warning(prog, "copyentity: can not modify world entity\n");
1761 if (out->priv.server->free)
1763 VM_Warning(prog, "copyentity: can not modify free entity\n");
1766 memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
1775 sets the color of a client and broadcasts the update to all connected clients
1777 setcolor(clientent, value)
1780 static void VM_SV_setcolor(prvm_prog_t *prog)
1785 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1786 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1787 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1789 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1791 Con_Print("tried to setcolor a non-client\n");
1795 client = svs.clients + entnum-1;
1798 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1799 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1802 if (client->old_colors != client->colors)
1804 client->old_colors = client->colors;
1805 // send notification to all clients
1806 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1807 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1808 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1816 effect(origin, modelname, startframe, framecount, framerate)
1819 static void VM_SV_effect(prvm_prog_t *prog)
1824 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1825 s = PRVM_G_STRING(OFS_PARM1);
1828 VM_Warning(prog, "effect: no model specified\n");
1832 i = SV_ModelIndex(s, 1);
1835 VM_Warning(prog, "effect: model not precached\n");
1839 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1841 VM_Warning(prog, "effect: framecount < 1\n");
1845 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1847 VM_Warning(prog, "effect: framerate < 1\n");
1851 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1852 SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1855 static void VM_SV_te_blood(prvm_prog_t *prog)
1857 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1858 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1860 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1861 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1863 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1864 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1865 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1867 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1868 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1869 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1871 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1872 SV_FlushBroadcastMessages();
1875 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1877 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1878 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1880 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1881 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1883 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1884 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1885 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1887 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1888 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1889 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1891 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1893 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1894 SV_FlushBroadcastMessages();
1897 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1899 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1900 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1901 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1907 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1908 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1909 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1910 SV_FlushBroadcastMessages();
1913 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1915 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1916 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1918 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1919 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1921 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1922 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1923 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1925 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1926 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1933 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1935 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1936 // gravity true/false
1937 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1940 SV_FlushBroadcastMessages();
1943 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1945 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1946 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1948 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1949 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1952 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1953 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1955 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1963 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1965 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1966 SV_FlushBroadcastMessages();
1969 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1971 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1972 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1974 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1975 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1977 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1978 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1979 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1983 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1985 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1989 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1991 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1992 SV_FlushBroadcastMessages();
1995 static void VM_SV_te_spark(prvm_prog_t *prog)
1997 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1998 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2000 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2001 MSG_WriteByte(&sv.datagram, TE_SPARK);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2004 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2005 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2007 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2008 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2009 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2011 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2012 SV_FlushBroadcastMessages();
2015 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2017 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2018 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2019 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2021 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2022 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2023 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2024 SV_FlushBroadcastMessages();
2027 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2029 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2030 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2031 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2033 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2034 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2035 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2036 SV_FlushBroadcastMessages();
2039 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2041 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2042 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2043 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2045 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2046 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2047 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2048 SV_FlushBroadcastMessages();
2051 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2053 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2054 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2055 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2058 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2059 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2060 SV_FlushBroadcastMessages();
2063 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2065 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2066 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2067 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2069 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2070 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2071 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2072 SV_FlushBroadcastMessages();
2075 static void VM_SV_te_customflash(prvm_prog_t *prog)
2077 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2078 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2080 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2081 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2083 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2084 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2085 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2087 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2089 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2091 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2092 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2093 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2094 SV_FlushBroadcastMessages();
2097 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2099 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2100 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2101 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2103 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2104 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2105 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2106 SV_FlushBroadcastMessages();
2109 static void VM_SV_te_spike(prvm_prog_t *prog)
2111 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2112 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2113 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2115 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2116 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2117 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2118 SV_FlushBroadcastMessages();
2121 static void VM_SV_te_superspike(prvm_prog_t *prog)
2123 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2124 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2125 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2127 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2128 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2129 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2130 SV_FlushBroadcastMessages();
2133 static void VM_SV_te_explosion(prvm_prog_t *prog)
2135 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2136 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2137 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2139 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2140 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2141 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2142 SV_FlushBroadcastMessages();
2145 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2147 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2148 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2149 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2151 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2152 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2153 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2154 SV_FlushBroadcastMessages();
2157 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2159 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2160 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2161 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2163 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2164 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2165 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2166 SV_FlushBroadcastMessages();
2169 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2171 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2172 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2173 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2175 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2176 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2177 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2178 SV_FlushBroadcastMessages();
2181 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2183 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2184 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2185 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2187 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2188 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2189 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2190 SV_FlushBroadcastMessages();
2193 static void VM_SV_te_teleport(prvm_prog_t *prog)
2195 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2196 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2197 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2199 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2200 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2201 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2202 SV_FlushBroadcastMessages();
2205 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2207 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2208 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2209 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2211 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2212 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2213 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2215 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2216 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2217 SV_FlushBroadcastMessages();
2220 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2222 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2223 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2224 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2226 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2230 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2232 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2233 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2234 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2235 SV_FlushBroadcastMessages();
2238 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2240 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2241 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2242 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2244 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2246 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2247 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2248 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2250 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2251 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2252 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2253 SV_FlushBroadcastMessages();
2256 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2258 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2259 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2260 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2262 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2264 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2265 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2266 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2268 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2269 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2270 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2271 SV_FlushBroadcastMessages();
2274 static void VM_SV_te_beam(prvm_prog_t *prog)
2276 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2277 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2278 MSG_WriteByte(&sv.datagram, TE_BEAM);
2280 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2282 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2283 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2284 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2286 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2287 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2288 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2289 SV_FlushBroadcastMessages();
2292 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2294 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2295 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2296 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2297 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2298 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2299 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2300 SV_FlushBroadcastMessages();
2303 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2305 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2306 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2307 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2309 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2310 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2311 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2313 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2314 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2315 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2317 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2318 SV_FlushBroadcastMessages();
2321 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2322 //this function originally written by KrimZon, made shorter by LordHavoc
2323 static void VM_SV_clientcommand(prvm_prog_t *prog)
2325 client_t *temp_client;
2327 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2329 //find client for this entity
2330 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2331 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2333 Con_Print("PF_clientcommand: entity is not a client\n");
2337 temp_client = host_client;
2338 host_client = svs.clients + i;
2339 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
2340 host_client = temp_client;
2343 //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)
2344 static void VM_SV_setattachment(prvm_prog_t *prog)
2346 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2347 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2348 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2351 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2353 if (e == prog->edicts)
2355 VM_Warning(prog, "setattachment: can not modify world entity\n");
2358 if (e->priv.server->free)
2360 VM_Warning(prog, "setattachment: can not modify free entity\n");
2364 if (tagentity == NULL)
2365 tagentity = prog->edicts;
2369 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2371 model = SV_GetModelFromEdict(tagentity);
2374 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2376 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);
2379 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));
2382 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2383 PRVM_serveredictfloat(e, tag_index) = tagindex;
2386 /////////////////////////////////////////
2387 // DP_MD3_TAGINFO extension coded by VorteX
2389 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2393 i = (int)PRVM_serveredictfloat(e, modelindex);
2394 if (i < 1 || i >= MAX_MODELS)
2397 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2400 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2407 Matrix4x4_CreateIdentity(tag_localmatrix);
2409 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2411 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2422 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2425 float pitchsign = 1;
2427 scale = PRVM_serveredictfloat(ent, scale);
2432 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);
2435 pitchsign = SV_GetPitchSign(prog, ent);
2436 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);
2440 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2443 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2445 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2446 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2447 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2448 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2450 *out = identitymatrix;
2454 // Warnings/errors code:
2455 // 0 - normal (everything all-right)
2458 // 3 - null or non-precached model
2459 // 4 - no tags with requested index
2460 // 5 - runaway loop at attachment chain
2461 extern cvar_t cl_bob;
2462 extern cvar_t cl_bobcycle;
2463 extern cvar_t cl_bobup;
2464 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2467 int modelindex, attachloop;
2468 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2471 *out = identitymatrix; // warnings and errors return identical matrix
2473 if (ent == prog->edicts)
2475 if (ent->priv.server->free)
2478 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2479 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2482 model = SV_GetModelByIndex(modelindex);
2484 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2485 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2486 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2488 tagmatrix = identitymatrix;
2489 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2493 if (attachloop >= 256) // prevent runaway looping
2495 // apply transformation by child's tagindex on parent entity and then
2496 // by parent entity itself
2497 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2498 if (ret && attachloop == 0)
2500 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2501 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2502 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2503 // next iteration we process the parent entity
2504 if (PRVM_serveredictedict(ent, tag_entity))
2506 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2507 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2514 // RENDER_VIEWMODEL magic
2515 if (PRVM_serveredictedict(ent, viewmodelforclient))
2517 Matrix4x4_Copy(&tagmatrix, out);
2518 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2520 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2521 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2524 // Cl_bob, ported from rendering code
2525 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2528 // LordHavoc: this code is *weird*, but not replacable (I think it
2529 // should be done in QC on the server, but oh well, quake is quake)
2530 // LordHavoc: figured out bobup: the time at which the sin is at 180
2531 // degrees (which allows lengthening or squishing the peak or valley)
2532 cycle = sv.time/cl_bobcycle.value;
2533 cycle -= (int)cycle;
2534 if (cycle < cl_bobup.value)
2535 cycle = sin(M_PI * cycle / cl_bobup.value);
2537 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2538 // bob is proportional to velocity in the xy plane
2539 // (don't count Z, or jumping messes it up)
2540 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;
2541 bob = bob*0.3 + bob*0.7*cycle;
2542 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2549 //float(entity ent, string tagname) gettagindex;
2551 static void VM_SV_gettagindex(prvm_prog_t *prog)
2554 const char *tag_name;
2557 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2559 ent = PRVM_G_EDICT(OFS_PARM0);
2560 tag_name = PRVM_G_STRING(OFS_PARM1);
2562 if (ent == prog->edicts)
2564 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2567 if (ent->priv.server->free)
2569 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2574 if (!SV_GetModelFromEdict(ent))
2575 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2578 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2580 if(developer_extra.integer)
2581 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2583 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2586 //vector(entity ent, float tagindex) gettaginfo;
2587 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2591 matrix4x4_t tag_matrix;
2592 matrix4x4_t tag_localmatrix;
2594 const char *tagname;
2596 vec3_t forward, left, up, origin;
2597 const dp_model_t *model;
2599 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2601 e = PRVM_G_EDICT(OFS_PARM0);
2602 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2604 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2605 Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
2606 VectorCopy(forward, PRVM_serverglobalvector(v_forward));
2607 VectorNegate(left, PRVM_serverglobalvector(v_right));
2608 VectorCopy(up, PRVM_serverglobalvector(v_up));
2609 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2610 model = SV_GetModelFromEdict(e);
2611 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2612 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2613 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2614 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2615 Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
2617 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2618 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2619 VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
2620 VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
2621 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2622 VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset));
2627 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2630 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2633 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2636 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2639 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2644 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2645 static void VM_SV_dropclient(prvm_prog_t *prog)
2648 client_t *oldhostclient;
2649 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2650 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2651 if (clientnum < 0 || clientnum >= svs.maxclients)
2653 VM_Warning(prog, "dropclient: not a client\n");
2656 if (!svs.clients[clientnum].active)
2658 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2661 oldhostclient = host_client;
2662 host_client = svs.clients + clientnum;
2663 SV_DropClient(false);
2664 host_client = oldhostclient;
2667 //entity() spawnclient (DP_SV_BOTCLIENT)
2668 static void VM_SV_spawnclient(prvm_prog_t *prog)
2672 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2673 prog->xfunction->builtinsprofile += 2;
2675 for (i = 0;i < svs.maxclients;i++)
2677 if (!svs.clients[i].active)
2679 prog->xfunction->builtinsprofile += 100;
2680 SV_ConnectClient (i, NULL);
2681 // this has to be set or else ClientDisconnect won't be called
2682 // we assume the qc will call ClientConnect...
2683 svs.clients[i].clientconnectcalled = true;
2684 ed = PRVM_EDICT_NUM(i + 1);
2688 VM_RETURN_EDICT(ed);
2691 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2692 static void VM_SV_clienttype(prvm_prog_t *prog)
2695 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2696 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2697 if (clientnum < 0 || clientnum >= svs.maxclients)
2698 PRVM_G_FLOAT(OFS_RETURN) = 3;
2699 else if (!svs.clients[clientnum].active)
2700 PRVM_G_FLOAT(OFS_RETURN) = 0;
2701 else if (svs.clients[clientnum].netconnection)
2702 PRVM_G_FLOAT(OFS_RETURN) = 1;
2704 PRVM_G_FLOAT(OFS_RETURN) = 2;
2711 string(string key) serverkey
2714 static void VM_SV_serverkey(prvm_prog_t *prog)
2716 char string[VM_STRINGTEMP_LENGTH];
2717 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2718 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2719 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2722 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2723 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2728 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2730 e = PRVM_G_EDICT(OFS_PARM0);
2731 if (e == prog->edicts)
2733 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2736 if (e->priv.server->free)
2738 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2741 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2742 if (i <= 0 || i >= MAX_MODELS)
2744 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2747 if (!sv.model_precache[i][0])
2749 VM_Warning(prog, "setmodelindex: model not precached\n");
2753 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2754 PRVM_serveredictfloat(e, modelindex) = i;
2756 mod = SV_GetModelByIndex(i);
2760 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2761 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2763 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2766 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2769 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2770 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2773 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2775 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2777 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2778 if (i <= 0 || i >= MAX_MODELS)
2780 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2783 if (!sv.model_precache[i][0])
2785 VM_Warning(prog, "modelnameforindex: model not precached\n");
2789 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2792 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2793 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2796 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2797 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2800 PRVM_G_FLOAT(OFS_RETURN) = i;
2803 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2804 static void VM_SV_trailparticles(prvm_prog_t *prog)
2807 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2809 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2812 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2813 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2814 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2815 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start);
2816 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end);
2817 MSG_WriteVector(&sv.datagram, start, sv.protocol);
2818 MSG_WriteVector(&sv.datagram, end, sv.protocol);
2819 SV_FlushBroadcastMessages();
2822 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2823 static void VM_SV_pointparticles(prvm_prog_t *prog)
2825 int effectnum, count;
2827 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2829 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2832 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2833 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2834 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2835 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2836 if (count == 1 && !VectorLength2(vel))
2839 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2840 MSG_WriteShort(&sv.datagram, effectnum);
2841 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2845 // 1+2+12+12+2=29 bytes
2846 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2847 MSG_WriteShort(&sv.datagram, effectnum);
2848 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2849 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2850 MSG_WriteShort(&sv.datagram, count);
2853 SV_FlushBroadcastMessages();
2856 //PF_setpause, // void(float pause) setpause = #531;
2857 static void VM_SV_setpause(prvm_prog_t *prog) {
2859 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2860 if (pauseValue != 0) { //pause the game
2862 sv.pausedstart = realtime;
2863 } else { //disable pause, in case it was enabled
2864 if (sv.paused != 0) {
2869 // send notification to all clients
2870 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2871 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2874 // #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.
2875 static void VM_SV_skel_create(prvm_prog_t *prog)
2877 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2878 dp_model_t *model = SV_GetModelByIndex(modelindex);
2879 skeleton_t *skeleton;
2881 PRVM_G_FLOAT(OFS_RETURN) = 0;
2882 if (!model || !model->num_bones)
2884 for (i = 0;i < MAX_EDICTS;i++)
2885 if (!prog->skeletons[i])
2887 if (i == MAX_EDICTS)
2889 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(prog->progs_mempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2890 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2891 skeleton->model = model;
2892 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2893 // initialize to identity matrices
2894 for (i = 0;i < skeleton->model->num_bones;i++)
2895 skeleton->relativetransforms[i] = identitymatrix;
2898 // #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
2899 static void VM_SV_skel_build(prvm_prog_t *prog)
2901 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2902 skeleton_t *skeleton;
2903 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2904 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2905 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2906 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2907 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2908 dp_model_t *model = SV_GetModelByIndex(modelindex);
2912 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2913 frameblend_t frameblend[MAX_FRAMEBLENDS];
2914 matrix4x4_t bonematrix;
2916 PRVM_G_FLOAT(OFS_RETURN) = 0;
2917 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2919 firstbone = max(0, firstbone);
2920 lastbone = min(lastbone, model->num_bones - 1);
2921 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2922 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2923 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time);
2924 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2926 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2928 memset(&bonematrix, 0, sizeof(bonematrix));
2929 for (blendindex = 0;blendindex < numblends;blendindex++)
2931 Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2932 Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp);
2934 Matrix4x4_Normalize3(&bonematrix, &bonematrix);
2935 Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac);
2937 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2940 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2941 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
2943 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2944 skeleton_t *skeleton;
2945 PRVM_G_FLOAT(OFS_RETURN) = 0;
2946 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2948 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2951 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2952 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
2954 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2955 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2956 skeleton_t *skeleton;
2957 PRVM_G_INT(OFS_RETURN) = 0;
2958 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2960 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2962 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
2965 // #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)
2966 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
2968 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2969 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2970 skeleton_t *skeleton;
2971 PRVM_G_FLOAT(OFS_RETURN) = 0;
2972 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2974 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2976 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2979 // #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
2980 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
2982 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2983 const char *tagname = PRVM_G_STRING(OFS_PARM1);
2984 skeleton_t *skeleton;
2985 PRVM_G_FLOAT(OFS_RETURN) = 0;
2986 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2988 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2991 // #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)
2992 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
2994 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2995 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2996 skeleton_t *skeleton;
2998 vec3_t forward, left, up, origin;
2999 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3000 VectorClear(PRVM_clientglobalvector(v_forward));
3001 VectorClear(PRVM_clientglobalvector(v_right));
3002 VectorClear(PRVM_clientglobalvector(v_up));
3003 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3005 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3007 matrix = skeleton->relativetransforms[bonenum];
3008 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3009 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3010 VectorNegate(left, PRVM_clientglobalvector(v_right));
3011 VectorCopy(up, PRVM_clientglobalvector(v_up));
3012 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3015 // #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)
3016 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
3018 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3019 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3020 skeleton_t *skeleton;
3023 vec3_t forward, left, up, origin;
3024 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3025 VectorClear(PRVM_clientglobalvector(v_forward));
3026 VectorClear(PRVM_clientglobalvector(v_right));
3027 VectorClear(PRVM_clientglobalvector(v_up));
3028 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3030 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3032 matrix = skeleton->relativetransforms[bonenum];
3033 // convert to absolute
3034 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3037 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3039 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3040 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3041 VectorNegate(left, PRVM_clientglobalvector(v_right));
3042 VectorCopy(up, PRVM_clientglobalvector(v_up));
3043 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3046 // #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)
3047 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3049 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3050 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3051 vec3_t forward, left, up, origin;
3052 skeleton_t *skeleton;
3054 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3056 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3058 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3059 VectorNegate(PRVM_clientglobalvector(v_right), left);
3060 VectorCopy(PRVM_clientglobalvector(v_up), up);
3061 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3062 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3063 skeleton->relativetransforms[bonenum] = matrix;
3066 // #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)
3067 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3069 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3070 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3071 vec3_t forward, left, up, origin;
3072 skeleton_t *skeleton;
3075 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3077 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3079 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3080 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3081 VectorNegate(PRVM_clientglobalvector(v_right), left);
3082 VectorCopy(PRVM_clientglobalvector(v_up), up);
3083 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3084 temp = skeleton->relativetransforms[bonenum];
3085 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3088 // #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)
3089 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3091 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3092 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3093 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3095 vec3_t forward, left, up, origin;
3096 skeleton_t *skeleton;
3099 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3101 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3102 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3103 VectorNegate(PRVM_clientglobalvector(v_right), left);
3104 VectorCopy(PRVM_clientglobalvector(v_up), up);
3105 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3106 firstbone = max(0, firstbone);
3107 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3108 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3110 temp = skeleton->relativetransforms[bonenum];
3111 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3115 // #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
3116 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3118 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3119 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3120 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3121 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3123 skeleton_t *skeletondst;
3124 skeleton_t *skeletonsrc;
3125 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3127 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3129 firstbone = max(0, firstbone);
3130 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3131 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3132 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3133 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3136 // #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)
3137 static void VM_SV_skel_delete(prvm_prog_t *prog)
3139 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3140 skeleton_t *skeleton;
3141 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3144 prog->skeletons[skeletonindex] = NULL;
3147 // #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
3148 static void VM_SV_frameforname(prvm_prog_t *prog)
3150 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3151 dp_model_t *model = SV_GetModelByIndex(modelindex);
3152 const char *name = PRVM_G_STRING(OFS_PARM1);
3154 PRVM_G_FLOAT(OFS_RETURN) = -1;
3155 if (!model || !model->animscenes)
3157 for (i = 0;i < model->numframes;i++)
3159 if (!strcasecmp(model->animscenes[i].name, name))
3161 PRVM_G_FLOAT(OFS_RETURN) = i;
3167 // #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.
3168 static void VM_SV_frameduration(prvm_prog_t *prog)
3170 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3171 dp_model_t *model = SV_GetModelByIndex(modelindex);
3172 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3173 PRVM_G_FLOAT(OFS_RETURN) = 0;
3174 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3176 if (model->animscenes[framenum].framerate)
3177 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3181 prvm_builtin_t vm_sv_builtins[] = {
3182 NULL, // #0 NULL function (not callable) (QUAKE)
3183 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3184 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3185 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3186 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3187 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3188 VM_break, // #6 void() break (QUAKE)
3189 VM_random, // #7 float() random (QUAKE)
3190 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3191 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3192 VM_error, // #10 void(string e) error (QUAKE)
3193 VM_objerror, // #11 void(string e) objerror (QUAKE)
3194 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3195 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3196 VM_spawn, // #14 entity() spawn (QUAKE)
3197 VM_remove, // #15 void(entity e) remove (QUAKE)
3198 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3199 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3200 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3201 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3202 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3203 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3204 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3205 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3206 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3207 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3208 VM_ftos, // #26 string(float f) ftos (QUAKE)
3209 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3210 VM_coredump, // #28 void() coredump (QUAKE)
3211 VM_traceon, // #29 void() traceon (QUAKE)
3212 VM_traceoff, // #30 void() traceoff (QUAKE)
3213 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3214 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3215 NULL, // #33 (QUAKE)
3216 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3217 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3218 VM_rint, // #36 float(float v) rint (QUAKE)
3219 VM_floor, // #37 float(float v) floor (QUAKE)
3220 VM_ceil, // #38 float(float v) ceil (QUAKE)
3221 NULL, // #39 (QUAKE)
3222 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3223 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3224 NULL, // #42 (QUAKE)
3225 VM_fabs, // #43 float(float f) fabs (QUAKE)
3226 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3227 VM_cvar, // #45 float(string s) cvar (QUAKE)
3228 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3229 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3230 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3231 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3232 NULL, // #50 (QUAKE)
3233 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3234 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3235 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3236 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3237 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3238 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3239 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3240 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3241 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3242 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3243 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3244 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3245 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3246 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3247 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3248 NULL, // #66 (QUAKE)
3249 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3250 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3251 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3252 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3253 NULL, // #71 (QUAKE)
3254 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3255 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3256 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3257 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3258 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3259 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3260 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3261 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3262 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3263 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3264 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3265 NULL, // #83 (QUAKE)
3266 NULL, // #84 (QUAKE)
3267 NULL, // #85 (QUAKE)
3268 NULL, // #86 (QUAKE)
3269 NULL, // #87 (QUAKE)
3270 NULL, // #88 (QUAKE)
3271 NULL, // #89 (QUAKE)
3272 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3273 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3274 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3275 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3276 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3277 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3278 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3279 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3280 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3281 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3282 // FrikaC and Telejano range #100-#199
3293 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3294 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3295 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3296 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3297 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3298 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3299 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3300 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3301 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3302 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3383 // FTEQW range #200-#299
3402 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3405 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3406 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3407 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3408 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3409 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3410 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3411 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3412 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3413 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3414 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3416 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3424 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3447 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.
3448 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
3449 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3450 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3451 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)
3452 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
3453 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)
3454 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)
3455 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)
3456 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)
3457 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)
3458 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
3459 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)
3460 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
3461 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.
3484 // CSQC range #300-#399
3485 NULL, // #300 void() clearscene (EXT_CSQC)
3486 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3487 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3488 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3489 NULL, // #304 void() renderscene (EXT_CSQC)
3490 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3491 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3492 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3493 NULL, // #308 void() R_EndPolygon
3495 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3496 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3500 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3501 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3502 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3503 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3504 NULL, // #319 void(string name) freepic (EXT_CSQC)
3505 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3506 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3507 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3508 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3509 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3510 NULL, // #325 void(void) drawresetcliparea
3515 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3516 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3517 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3518 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3519 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3520 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3521 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3522 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3523 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3524 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3525 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3526 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3527 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3528 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3529 NULL, // #344 vector() getmousepos (EXT_CSQC)
3530 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3531 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3532 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3533 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3534 NULL, // #349 float() isdemo (EXT_CSQC)
3535 VM_isserver, // #350 float() isserver (EXT_CSQC)
3536 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3537 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3538 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3539 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3545 NULL, // #360 float() readbyte (EXT_CSQC)
3546 NULL, // #361 float() readchar (EXT_CSQC)
3547 NULL, // #362 float() readshort (EXT_CSQC)
3548 NULL, // #363 float() readlong (EXT_CSQC)
3549 NULL, // #364 float() readcoord (EXT_CSQC)
3550 NULL, // #365 float() readangle (EXT_CSQC)
3551 NULL, // #366 string() readstring (EXT_CSQC)
3552 NULL, // #367 float() readfloat (EXT_CSQC)
3585 // LordHavoc's range #400-#499
3586 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3587 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3588 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3589 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3590 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3591 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3592 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3593 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3594 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)
3595 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3596 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3597 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3598 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3599 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3600 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3601 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3602 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3603 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3604 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3605 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3606 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3607 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3608 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3609 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3610 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3611 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3612 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3613 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3614 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3615 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3616 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3617 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3618 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3619 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3620 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3621 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3622 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3623 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3624 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3625 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3626 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3627 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3628 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3629 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3630 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3631 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3632 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3633 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3634 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3635 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3636 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3637 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3638 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3639 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3640 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3641 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3642 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3643 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3645 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3646 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3647 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3648 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3649 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3650 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3651 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3652 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3653 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3654 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3655 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3657 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3658 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3659 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3660 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3661 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3662 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3663 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3664 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3665 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3666 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3667 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3668 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3669 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3670 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3671 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3672 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3680 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3681 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3682 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3683 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3684 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3685 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3686 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3687 VM_SV_WritePicture, // #501
3689 VM_whichpack, // #503 string(string) whichpack = #503;
3696 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3697 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3698 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3699 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)
3700 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3701 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3702 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3703 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3704 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3705 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3715 VM_loadfromdata, // #529
3716 VM_loadfromfile, // #530
3717 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3719 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3720 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3721 VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP)
3722 VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP)
3723 VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP)
3724 VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP)
3726 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3727 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3728 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3791 VM_callfunction, // #605
3792 VM_writetofile, // #606
3793 VM_isfunction, // #607
3799 VM_parseentitydata, // #613
3810 VM_SV_getextresponse, // #624 string getextresponse(void)
3813 VM_sprintf, // #627 string sprintf(string format, ...)
3814 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3815 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3825 VM_digest_hex, // #639
3828 VM_coverage, // #642
3832 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3834 void SVVM_init_cmd(prvm_prog_t *prog)
3839 void SVVM_reset_cmd(prvm_prog_t *prog)
3841 World_End(&sv.world);
3843 if(prog->loaded && PRVM_serverfunction(SV_Shutdown))
3845 func_t s = PRVM_serverfunction(SV_Shutdown);
3846 PRVM_serverglobalfloat(time) = sv.time;
3847 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3848 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");