6 //============================================================================
11 const char *vm_sv_extensions =
16 "DP_CON_ALIASPARAMETERS "
25 "DP_CSQC_ENTITYWORLDOBJECT "
26 "DP_CSQC_ENTITYMODELLIGHT "
27 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
29 "DP_CSQC_MINFPS_QUALITY "
30 "DP_CSQC_MULTIFRAME_INTERPOLATION "
31 "DP_CSQC_BOXPARTICLES "
32 "DP_CSQC_SPAWNPARTICLE "
33 "DP_CSQC_QUERYRENDERENTITY "
34 "DP_CSQC_ROTATEMOVES "
36 "DP_CSQC_V_CALCREFDEF_WIP1 "
37 "DP_CSQC_V_CALCREFDEF_WIP2 "
41 "DP_EF_DYNAMICMODELLIGHT "
50 "DP_EF_RESTARTANIM_BIT "
55 "DP_ENT_CUSTOMCOLORMAP "
56 "DP_ENT_EXTERIORMODELTOCLIENT "
59 "DP_ENT_LOWPRECISION "
61 "DP_ENT_TRAILEFFECTNUM "
63 "DP_GFX_EXTERNALTEXTURES "
64 "DP_GFX_EXTERNALTEXTURES_PERMAP "
66 "DP_GFX_MODEL_INTERPOLATION "
67 "DP_GFX_QUAKE3MODELTAGS "
71 "DP_GFX_FONTS_FREETYPE "
73 "DP_FONT_VARIABLEWIDTH "
75 "DP_HALFLIFE_MAP_CVAR "
78 "DP_LIGHTSTYLE_STATICVALUE "
82 "DP_MOVETYPEBOUNCEMISSILE "
83 "DP_MOVETYPEFLYWORLDONLY "
86 "DP_QC_ASINACOSATANATAN2TAN "
92 "DP_QC_CVAR_DEFSTRING "
93 "DP_QC_CVAR_DESCRIPTION "
97 "DP_QC_DIGEST_SHA256 "
100 "DP_QC_ENTITYSTRING "
102 "DP_QC_EXTRESPONSEPACKET "
104 "DP_QC_FINDCHAINFLAGS "
105 "DP_QC_FINDCHAINFLOAT "
106 "DP_QC_FINDCHAIN_TOFIELD "
112 "DP_QC_GETSURFACETRIANGLE "
113 "DP_QC_GETSURFACEPOINTATTRIBUTE "
115 "DP_QC_GETTAGINFO_BONEPROPERTIES "
117 "DP_QC_GETTIME_CDTRACK "
121 "DP_QC_MULTIPLETEMPSTRINGS "
122 "DP_QC_NUM_FOR_EDICT "
124 "DP_QC_SINCOSSQRTPOW "
127 "DP_QC_STRINGBUFFERS "
128 "DP_QC_STRINGBUFFERS_CVARLIST "
129 "DP_QC_STRINGBUFFERS_EXT_WIP "
130 "DP_QC_STRINGCOLORFUNCTIONS "
131 "DP_QC_STRING_CASE_FUNCTIONS "
133 "DP_QC_TOKENIZEBYSEPARATOR "
134 "DP_QC_TOKENIZE_CONSOLE "
137 "DP_QC_TRACE_MOVETYPE_HITMODEL "
138 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
139 "DP_QC_UNLIMITEDTEMPSTRINGS "
143 "DP_QC_VECTOANGLES_WITH_ROLL "
144 "DP_QC_VECTORVECTORS "
151 "DP_SKELETONOBJECTS "
152 "DP_SND_DIRECTIONLESSATTNNONE "
154 "DP_SND_SOUND7_WIP1 "
155 "DP_SND_SOUND7_WIP2 "
159 "DP_SND_GETSOUNDTIME "
161 "DP_VIDEO_SUBTITLES "
165 "DP_SV_BOUNCEFACTOR "
166 "DP_SV_CLIENTCAMERA "
167 "DP_SV_CLIENTCOLORS "
170 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
171 "DP_SV_DISABLECLIENTPREDICTION "
172 "DP_SV_DISCARDABLEDEMO "
173 "DP_SV_DRAWONLYTOCLIENT "
176 "DP_SV_ENTITYCONTENTSTRANSITION "
177 "DP_SV_MODELFLAGS_AS_EFFECTS "
178 "DP_SV_MOVETYPESTEP_LANDEVENT "
180 "DP_SV_NODRAWTOCLIENT "
181 "DP_SV_ONENTITYNOSPAWNFUNCTION "
182 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
184 "DP_SV_PING_PACKETLOSS "
185 "DP_SV_PLAYERPHYSICS "
187 "DP_SV_POINTPARTICLES "
189 "DP_SV_PRECACHEANYTIME "
193 "DP_SV_ROTATINGBMODEL "
197 "DP_SV_SPAWNFUNC_PREFIX "
198 "DP_SV_WRITEPICTURE "
199 "DP_SV_WRITEUNTERMINATEDSTRING "
203 "DP_TE_EXPLOSIONRGB "
205 "DP_TE_PARTICLECUBE "
206 "DP_TE_PARTICLERAIN "
207 "DP_TE_PARTICLESNOW "
209 "DP_TE_QUADEFFECTS1 "
212 "DP_TE_STANDARDEFFECTBUILTINS "
213 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
218 "FTE_CSQC_SKELETONOBJECTS "
221 "KRIMZON_SV_PARSECLIENTCOMMAND "
224 "NEXUIZ_PLAYERMODEL "
226 "PRYDON_CLIENTCURSOR "
227 "TENEBRAE_GFX_DLIGHTS "
231 //"EXT_CSQC " // not ready yet
238 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.
240 setorigin (entity, origin)
243 static void VM_SV_setorigin(prvm_prog_t *prog)
247 VM_SAFEPARMCOUNT(2, VM_SV_setorigin);
249 e = PRVM_G_EDICT(OFS_PARM0);
250 if (e == prog->edicts)
252 VM_Warning(prog, "setorigin: can not modify world entity\n");
255 if (e->priv.server->free)
257 VM_Warning(prog, "setorigin: can not modify free entity\n");
260 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), PRVM_serveredictvector(e, origin));
261 if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
262 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
266 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
267 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qboolean rotate)
271 for (i=0 ; i<3 ; i++)
273 prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
275 // set derived values
276 VectorCopy (min, PRVM_serveredictvector(e, mins));
277 VectorCopy (max, PRVM_serveredictvector(e, maxs));
278 VectorSubtract (max, min, PRVM_serveredictvector(e, size));
287 the size box is rotated by the current angle
288 LadyHavoc: no it isn't...
290 setsize (entity, minvector, maxvector)
293 static void VM_SV_setsize(prvm_prog_t *prog)
298 VM_SAFEPARMCOUNT(3, VM_SV_setsize);
300 e = PRVM_G_EDICT(OFS_PARM0);
301 if (e == prog->edicts)
303 VM_Warning(prog, "setsize: can not modify world entity\n");
306 if (e->priv.server->free)
308 VM_Warning(prog, "setsize: can not modify free entity\n");
311 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), mins);
312 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), maxs);
313 SetMinMaxSize(prog, e, mins, maxs, false);
321 setmodel(entity, model)
324 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
325 static void VM_SV_setmodel(prvm_prog_t *prog)
331 VM_SAFEPARMCOUNT(2, VM_SV_setmodel);
333 e = PRVM_G_EDICT(OFS_PARM0);
334 if (e == prog->edicts)
336 VM_Warning(prog, "setmodel: can not modify world entity\n");
339 if (e->priv.server->free)
341 VM_Warning(prog, "setmodel: can not modify free entity\n");
344 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
345 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
346 PRVM_serveredictfloat(e, modelindex) = i;
348 mod = SV_GetModelByIndex(i);
352 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
353 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
355 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
358 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
365 single print to a specific client
367 sprint(clientent, value)
370 static void VM_SV_sprint(prvm_prog_t *prog)
374 char string[VM_STRINGTEMP_LENGTH];
376 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
378 VM_VarString(prog, 1, string, sizeof(string));
380 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
381 // LadyHavoc: div0 requested that sprintto world operate like print
388 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
390 VM_Warning(prog, "tried to centerprint to a non-client\n");
394 client = svs.clients + entnum-1;
395 if (!client->netconnection)
398 MSG_WriteChar(&client->netconnection->message,svc_print);
399 MSG_WriteString(&client->netconnection->message, string);
407 single print to a specific client
409 centerprint(clientent, value)
412 static void VM_SV_centerprint(prvm_prog_t *prog)
416 char string[VM_STRINGTEMP_LENGTH];
418 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
420 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
422 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
424 VM_Warning(prog, "tried to centerprint to a non-client\n");
428 client = svs.clients + entnum-1;
429 if (!client->netconnection)
432 VM_VarString(prog, 1, string, sizeof(string));
433 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
434 MSG_WriteString(&client->netconnection->message, string);
441 particle(origin, color, count)
444 static void VM_SV_particle(prvm_prog_t *prog)
450 VM_SAFEPARMCOUNT(4, VM_SV_particle);
452 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
453 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
454 color = (int)PRVM_G_FLOAT(OFS_PARM2);
455 count = (int)PRVM_G_FLOAT(OFS_PARM3);
456 SV_StartParticle (org, dir, color, count);
466 static void VM_SV_ambientsound(prvm_prog_t *prog)
470 prvm_vec_t vol, attenuation;
473 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
475 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
476 samp = PRVM_G_STRING(OFS_PARM1);
477 vol = PRVM_G_FLOAT(OFS_PARM2);
478 attenuation = PRVM_G_FLOAT(OFS_PARM3);
480 // check to see if samp was properly precached
481 soundnum = SV_SoundIndex(samp, 1);
489 // add an svc_spawnambient command to the level signon packet
492 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
494 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
496 MSG_WriteVector(&sv.signon, pos, sv.protocol);
498 if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
499 MSG_WriteShort (&sv.signon, soundnum);
501 MSG_WriteByte (&sv.signon, soundnum);
503 MSG_WriteByte (&sv.signon, (int)(vol*255));
504 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
512 Each entity can have eight independant sound sources, like voice,
515 Channel 0 is an auto-allocate channel, the others override anything
516 already running on that entity/channel pair.
518 An attenuation of 0 will play full volume everywhere in the level.
519 Larger attenuations will drop off.
523 static void VM_SV_sound(prvm_prog_t *prog)
527 prvm_edict_t *entity;
533 VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
535 entity = PRVM_G_EDICT(OFS_PARM0);
536 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
537 sample = PRVM_G_STRING(OFS_PARM2);
538 nvolume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
541 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
545 attenuation = PRVM_G_FLOAT(OFS_PARM4);
549 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
554 if(channel >= 8 && channel <= 15) // weird QW feature
556 flags |= CHANNELFLAG_RELIABLE;
562 // LadyHavoc: we only let the qc set certain flags, others are off-limits
563 flags = (int)PRVM_G_FLOAT(OFS_PARM6) & (CHANNELFLAG_RELIABLE | CHANNELFLAG_FORCELOOP | CHANNELFLAG_PAUSED | CHANNELFLAG_FULLVOLUME);
566 if (nvolume < 0 || nvolume > 255)
568 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
572 if (attenuation < 0 || attenuation > 4)
574 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
578 channel = CHAN_USER2ENGINE(channel);
580 if (!IS_CHAN(channel))
582 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
586 SV_StartSound (entity, channel, sample, nvolume, attenuation, flags & CHANNELFLAG_RELIABLE, pitchchange);
593 Follows the same logic as VM_SV_sound, except instead of
594 an entity, an origin for the sound is provided, and channel
595 is omitted (since no entity is being tracked).
599 static void VM_SV_pointsound(prvm_prog_t *prog)
607 VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
609 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
610 sample = PRVM_G_STRING(OFS_PARM1);
611 nvolume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
612 attenuation = PRVM_G_FLOAT(OFS_PARM3);
613 pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
615 if (nvolume < 0 || nvolume > 255)
617 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
621 if (attenuation < 0 || attenuation > 4)
623 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
627 SV_StartPointSound (org, sample, nvolume, attenuation, pitchchange);
634 Used for use tracing and shot targeting
635 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
636 if the tryents flag is set.
638 traceline (vector1, vector2, movetype, ignore)
641 static void VM_SV_traceline(prvm_prog_t *prog)
648 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
650 prog->xfunction->builtinsprofile += 30;
652 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
653 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), v2);
654 move = (int)PRVM_G_FLOAT(OFS_PARM2);
655 ent = PRVM_G_EDICT(OFS_PARM3);
657 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]))
658 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));
660 trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtracelinelength.value);
662 VM_SetTraceGlobals(prog, &trace);
670 Used for use tracing and shot targeting
671 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
672 if the tryents flag is set.
674 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
677 // LadyHavoc: added this for my own use, VERY useful, similar to traceline
678 static void VM_SV_tracebox(prvm_prog_t *prog)
680 vec3_t v1, v2, m1, m2;
685 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
687 prog->xfunction->builtinsprofile += 30;
689 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
690 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), m1);
691 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), m2);
692 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), v2);
693 move = (int)PRVM_G_FLOAT(OFS_PARM4);
694 ent = PRVM_G_EDICT(OFS_PARM5);
696 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]))
697 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));
699 trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtraceboxlength.value);
701 VM_SetTraceGlobals(prog, &trace);
704 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
708 vec3_t move, end, tossentorigin, tossentmins, tossentmaxs;
709 vec3_t original_origin;
710 vec3_t original_velocity;
711 vec3_t original_angles;
712 vec3_t original_avelocity;
715 VectorCopy(PRVM_serveredictvector(tossent, origin) , original_origin );
716 VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
717 VectorCopy(PRVM_serveredictvector(tossent, angles) , original_angles );
718 VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
720 gravity = PRVM_serveredictfloat(tossent, gravity);
723 gravity *= sv_gravity.value * 0.025;
725 for (i = 0;i < 200;i++) // LadyHavoc: sanity check; never trace more than 10 seconds
727 SV_CheckVelocity (tossent);
728 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
729 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
730 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
731 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
732 VectorCopy(PRVM_serveredictvector(tossent, origin), tossentorigin);
733 VectorCopy(PRVM_serveredictvector(tossent, mins), tossentmins);
734 VectorCopy(PRVM_serveredictvector(tossent, maxs), tossentmaxs);
735 trace = SV_TraceBox(tossentorigin, tossentmins, tossentmaxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent), 0, 0, collision_extendmovelength.value);
736 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
737 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
739 if (trace.fraction < 1)
743 VectorCopy(original_origin , PRVM_serveredictvector(tossent, origin) );
744 VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
745 VectorCopy(original_angles , PRVM_serveredictvector(tossent, angles) );
746 VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
751 static void VM_SV_tracetoss(prvm_prog_t *prog)
755 prvm_edict_t *ignore;
757 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
759 prog->xfunction->builtinsprofile += 600;
761 ent = PRVM_G_EDICT(OFS_PARM0);
762 if (ent == prog->edicts)
764 VM_Warning(prog, "tracetoss: can not use world entity\n");
767 ignore = PRVM_G_EDICT(OFS_PARM1);
769 trace = SV_Trace_Toss(prog, ent, ignore);
771 VM_SetTraceGlobals(prog, &trace);
774 //============================================================================
776 static int checkpvsbytes;
777 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
779 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
785 // cycle to the next one
787 check = bound(1, check, svs.maxclients);
788 if (check == svs.maxclients)
796 prog->xfunction->builtinsprofile++;
798 if (i == svs.maxclients+1)
800 // look up the client's edict
801 ent = PRVM_EDICT_NUM(i);
802 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
803 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
805 // found a valid client (possibly the same one again)
809 // get the PVS for the entity
810 VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
812 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
813 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
822 Returns a client (or object that has a client enemy) that would be a
825 If there is more than one valid option, they are cycled each frame
827 If (self.origin + self.viewofs) is not in the PVS of the current target,
828 it is not returned at all.
833 int c_invis, c_notvis;
834 static void VM_SV_checkclient(prvm_prog_t *prog)
836 prvm_edict_t *ent, *self;
839 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
841 // find a new check if on a new frame
842 if (sv.time - sv.lastchecktime >= 0.1)
844 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
845 sv.lastchecktime = sv.time;
848 // return check if it might be visible
849 ent = PRVM_EDICT_NUM(sv.lastcheck);
850 if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
852 VM_RETURN_EDICT(prog->edicts);
856 // if current entity can't possibly see the check entity, return 0
857 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
858 VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
859 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
862 VM_RETURN_EDICT(prog->edicts);
866 // might be able to see it
868 VM_RETURN_EDICT(ent);
871 //============================================================================
877 Checks if an entity is in a point's PVS.
878 Should be fast but can be inexact.
880 float checkpvs(vector viewpos, entity viewee) = #240;
883 static void VM_SV_checkpvs(prvm_prog_t *prog)
885 vec3_t viewpos, absmin, absmax;
886 prvm_edict_t *viewee;
891 unsigned char fatpvs[MAX_MAP_LEAFS/8];
894 VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
895 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
896 viewee = PRVM_G_EDICT(OFS_PARM1);
898 if(viewee->priv.server->free)
900 VM_Warning(prog, "checkpvs: can not check free entity\n");
901 PRVM_G_FLOAT(OFS_RETURN) = 4;
906 if(!sv.worldmodel || !sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
908 // no PVS support on this worldmodel... darn
909 PRVM_G_FLOAT(OFS_RETURN) = 3;
912 pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
915 // viewpos isn't in any PVS... darn
916 PRVM_G_FLOAT(OFS_RETURN) = 2;
919 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
920 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
921 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, absmin, absmax);
923 // using fat PVS like FTEQW does (slow)
924 if(!sv.worldmodel || !sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
926 // no PVS support on this worldmodel... darn
927 PRVM_G_FLOAT(OFS_RETURN) = 3;
930 fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
933 // viewpos isn't in any PVS... darn
934 PRVM_G_FLOAT(OFS_RETURN) = 2;
937 VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
938 VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
939 PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, absmin, absmax);
948 Sends text over to the client's execution buffer
950 stuffcmd (clientent, value, ...)
953 static void VM_SV_stuffcmd(prvm_prog_t *prog)
957 char string[VM_STRINGTEMP_LENGTH];
959 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
961 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
962 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
964 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
968 VM_VarString(prog, 1, string, sizeof(string));
971 host_client = svs.clients + entnum-1;
972 Host_ClientCommands ("%s", string);
980 Returns a chain of entities that have origins within a spherical area
982 findradius (origin, radius)
985 static void VM_SV_findradius(prvm_prog_t *prog)
987 prvm_edict_t *ent, *chain;
988 vec_t radius, radius2;
989 vec3_t org, eorg, mins, maxs;
992 static prvm_edict_t *touchedicts[MAX_EDICTS];
995 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
998 chainfield = PRVM_G_INT(OFS_PARM2);
1000 chainfield = prog->fieldoffsets.chain;
1002 prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
1004 chain = (prvm_edict_t *)prog->edicts;
1006 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1007 radius = PRVM_G_FLOAT(OFS_PARM1);
1008 radius2 = radius * radius;
1010 mins[0] = org[0] - (radius + 1);
1011 mins[1] = org[1] - (radius + 1);
1012 mins[2] = org[2] - (radius + 1);
1013 maxs[0] = org[0] + (radius + 1);
1014 maxs[1] = org[1] + (radius + 1);
1015 maxs[2] = org[2] + (radius + 1);
1016 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1017 if (numtouchedicts > MAX_EDICTS)
1019 // this never happens
1020 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1021 numtouchedicts = MAX_EDICTS;
1023 for (i = 0;i < numtouchedicts;i++)
1025 ent = touchedicts[i];
1026 prog->xfunction->builtinsprofile++;
1027 // Quake did not return non-solid entities but darkplaces does
1028 // (note: this is the reason you can't blow up fallen zombies)
1029 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1031 // LadyHavoc: compare against bounding box rather than center so it
1032 // doesn't miss large objects, and use DotProduct instead of Length
1033 // for a major speedup
1034 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1035 if (sv_gameplayfix_findradiusdistancetobox.integer)
1037 eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1038 eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1039 eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1042 VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1043 if (DotProduct(eorg, eorg) < radius2)
1045 PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1050 VM_RETURN_EDICT(chain);
1053 static void VM_SV_precache_sound(prvm_prog_t *prog)
1055 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1056 PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1059 static void VM_SV_precache_model(prvm_prog_t *prog)
1061 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1062 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1063 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1070 float(float yaw, float dist[, settrace]) walkmove
1073 static void VM_SV_walkmove(prvm_prog_t *prog)
1082 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1084 // assume failure if it returns early
1085 PRVM_G_FLOAT(OFS_RETURN) = 0;
1087 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1088 if (ent == prog->edicts)
1090 VM_Warning(prog, "walkmove: can not modify world entity\n");
1093 if (ent->priv.server->free)
1095 VM_Warning(prog, "walkmove: can not modify free entity\n");
1098 yaw = PRVM_G_FLOAT(OFS_PARM0);
1099 dist = PRVM_G_FLOAT(OFS_PARM1);
1100 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1102 if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1105 yaw = yaw*M_PI*2 / 360;
1107 move[0] = cos(yaw)*dist;
1108 move[1] = sin(yaw)*dist;
1111 // save program state, because SV_movestep may call other progs
1112 oldf = prog->xfunction;
1113 oldself = PRVM_serverglobaledict(self);
1115 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1118 // restore program state
1119 prog->xfunction = oldf;
1120 PRVM_serverglobaledict(self) = oldself;
1131 static void VM_SV_droptofloor(prvm_prog_t *prog)
1134 vec3_t end, entorigin, entmins, entmaxs;
1137 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1139 // assume failure if it returns early
1140 PRVM_G_FLOAT(OFS_RETURN) = 0;
1142 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1143 if (ent == prog->edicts)
1145 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1148 if (ent->priv.server->free)
1150 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1154 VectorCopy (PRVM_serveredictvector(ent, origin), end);
1157 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1158 SV_NudgeOutOfSolid(ent);
1160 VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
1161 VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
1162 VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
1163 trace = SV_TraceBox(entorigin, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
1164 if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1167 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]);
1168 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1169 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
1170 VectorSubtract(trace.endpos, offset, trace.endpos);
1171 if (trace.startsolid)
1173 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]);
1175 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1176 PRVM_serveredictedict(ent, groundentity) = 0;
1177 PRVM_G_FLOAT(OFS_RETURN) = 1;
1179 else if (trace.fraction < 1)
1181 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]);
1182 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1183 if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1184 SV_NudgeOutOfSolid(ent);
1186 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1187 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1188 PRVM_G_FLOAT(OFS_RETURN) = 1;
1189 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1190 ent->priv.server->suspendedinairflag = true;
1195 if (!trace.allsolid && trace.fraction < 1)
1197 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1199 PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1200 PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1201 PRVM_G_FLOAT(OFS_RETURN) = 1;
1202 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1203 ent->priv.server->suspendedinairflag = true;
1212 void(float style, string value) lightstyle
1215 static void VM_SV_lightstyle(prvm_prog_t *prog)
1222 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1224 style = (int)PRVM_G_FLOAT(OFS_PARM0);
1225 val = PRVM_G_STRING(OFS_PARM1);
1227 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1228 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1231 // change the string in sv
1232 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1234 // send message to all clients on this server
1235 if (sv.state != ss_active)
1238 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1240 if (client->active && client->netconnection)
1242 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1243 MSG_WriteChar (&client->netconnection->message,style);
1244 MSG_WriteString (&client->netconnection->message, val);
1254 static void VM_SV_checkbottom(prvm_prog_t *prog)
1256 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1257 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1265 static void VM_SV_pointcontents(prvm_prog_t *prog)
1268 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1269 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point);
1270 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(SV_PointSuperContents(point));
1277 Pick a vector for the player to shoot along
1278 vector aim(entity, missilespeed)
1281 static void VM_SV_aim(prvm_prog_t *prog)
1283 prvm_edict_t *ent, *check, *bestent;
1284 vec3_t start, dir, end, bestdir;
1287 float dist, bestdist;
1290 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1292 // assume failure if it returns early
1293 VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1294 // if sv_aim is so high it can't possibly accept anything, skip out early
1295 if (sv_aim.value >= 1)
1298 ent = PRVM_G_EDICT(OFS_PARM0);
1299 if (ent == prog->edicts)
1301 VM_Warning(prog, "aim: can not use world entity\n");
1304 if (ent->priv.server->free)
1306 VM_Warning(prog, "aim: can not use free entity\n");
1309 //speed = PRVM_G_FLOAT(OFS_PARM1);
1311 VectorCopy (PRVM_serveredictvector(ent, origin), start);
1314 // try sending a trace straight
1315 VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1316 VectorMA (start, 2048, dir, end);
1317 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1318 if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1319 && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1321 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1326 // try all possible entities
1327 VectorCopy (dir, bestdir);
1328 bestdist = sv_aim.value;
1331 check = PRVM_NEXT_EDICT(prog->edicts);
1332 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1334 prog->xfunction->builtinsprofile++;
1335 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1339 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1340 continue; // don't aim at teammate
1341 for (j=0 ; j<3 ; j++)
1342 end[j] = PRVM_serveredictvector(check, origin)[j]
1343 + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1344 VectorSubtract (end, start, dir);
1345 VectorNormalize (dir);
1346 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1347 if (dist < bestdist)
1348 continue; // to far to turn
1349 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1350 if (tr.ent == check)
1351 { // can shoot at this one
1359 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1360 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1361 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1363 VectorNormalize (end);
1364 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1368 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1373 ===============================================================================
1377 ===============================================================================
1380 #define MSG_BROADCAST 0 // unreliable to all
1381 #define MSG_ONE 1 // reliable to one (msg_entity)
1382 #define MSG_ALL 2 // reliable to all
1383 #define MSG_INIT 3 // write to the init string
1384 #define MSG_ENTITY 5
1386 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1392 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1396 return &sv.datagram;
1399 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1400 entnum = PRVM_NUM_FOR_EDICT(ent);
1401 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1403 VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1404 return &sv.reliable_datagram;
1407 return &svs.clients[entnum-1].netconnection->message;
1410 VM_Warning(prog, "WriteDest: bad destination\n");
1412 return &sv.reliable_datagram;
1418 return sv.writeentitiestoclient_msg;
1424 static void VM_SV_WriteByte(prvm_prog_t *prog)
1426 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1427 MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1430 static void VM_SV_WriteChar(prvm_prog_t *prog)
1432 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1433 MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1436 static void VM_SV_WriteShort(prvm_prog_t *prog)
1438 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1439 MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1442 static void VM_SV_WriteLong(prvm_prog_t *prog)
1444 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1445 MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1448 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1450 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1451 MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1454 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1456 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1457 MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1460 static void VM_SV_WriteString(prvm_prog_t *prog)
1462 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1463 MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1466 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1468 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1469 MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1473 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1475 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1476 MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1479 // writes a picture as at most size bytes of data
1481 // IMGNAME \0 SIZE(short) IMGDATA
1482 // if failed to read/compress:
1484 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1485 static void VM_SV_WritePicture(prvm_prog_t *prog)
1487 const char *imgname;
1491 VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1493 imgname = PRVM_G_STRING(OFS_PARM1);
1494 size = (size_t) PRVM_G_FLOAT(OFS_PARM2);
1498 MSG_WriteString(WriteDest(prog), imgname);
1499 if(Image_Compress(imgname, size, &buf, &size))
1502 MSG_WriteShort(WriteDest(prog), (int)size);
1503 SZ_Write(WriteDest(prog), (unsigned char *) buf, (int)size);
1508 MSG_WriteShort(WriteDest(prog), 0);
1512 //////////////////////////////////////////////////////////
1514 static void VM_SV_makestatic(prvm_prog_t *prog)
1519 // allow 0 parameters due to an id1 qc bug in which this function is used
1520 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1521 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1523 if (prog->argc >= 1)
1524 ent = PRVM_G_EDICT(OFS_PARM0);
1526 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1527 if (ent == prog->edicts)
1529 VM_Warning(prog, "makestatic: can not modify world entity\n");
1532 if (ent->priv.server->free)
1534 VM_Warning(prog, "makestatic: can not modify free entity\n");
1539 if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1544 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1545 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1546 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1548 else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1550 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1551 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1552 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1556 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1557 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1558 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1561 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1562 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1563 for (i=0 ; i<3 ; i++)
1565 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1566 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1569 // throw the entity away now
1570 PRVM_ED_Free(prog, ent);
1573 //=============================================================================
1580 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1586 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1588 ent = PRVM_G_EDICT(OFS_PARM0);
1589 i = PRVM_NUM_FOR_EDICT(ent);
1590 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1592 Con_Print("tried to setspawnparms on a non-client\n");
1596 // copy spawn parms out of the client_t
1597 client = svs.clients + i-1;
1598 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1599 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1606 Returns a color vector indicating the lighting at the requested point.
1608 (Internal Operation note: actually measures the light beneath the point, just like
1609 the model lighting on the client)
1614 static void VM_SV_getlight(prvm_prog_t *prog)
1616 vec3_t ambientcolor, diffusecolor, diffusenormal;
1618 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1619 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
1620 VectorClear(ambientcolor);
1621 VectorClear(diffusecolor);
1622 VectorClear(diffusenormal);
1623 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1624 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1625 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1630 unsigned char type; // 1/2/8 or 0 to indicate unused
1634 static customstat_t vm_customstats[MAX_CL_STATS]; // matches the regular stat numbers, but only MIN_VM_STAT to MAX_VM_STAT range is used if things are working properly (can register stats from MAX_VM_STAT to MAX_CL_STATS but will warn)
1635 static int vm_customstats_last;
1637 void VM_CustomStats_Clear (void)
1639 memset(vm_customstats, 0, sizeof(vm_customstats));
1640 vm_customstats_last = -1;
1643 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1645 prvm_prog_t *prog = SVVM_prog;
1653 for(i=MIN_VM_STAT; i<=vm_customstats_last ;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] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1664 stats[i+1] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1665 stats[i+2] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1666 stats[i+3] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1668 //float field sent as-is
1670 // can't directly use PRVM_E_INT on the field because it may be PRVM_64 and a double is not the representation we want to send
1671 u.f = PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1674 //integer value of float field
1676 stats[i] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1684 extern cvar_t sv_gameplayfix_customstats;
1686 // void(float index, float type, .void field) SV_AddStat = #232;
1687 // Set up an auto-sent player stat.
1688 // Client's get thier own fields sent to them. Index may not be less than 32.
1689 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1690 // 1: string (4 stats carrying a total of 16 charactures)
1691 // 2: float (one stat, float converted to an integer for transportation)
1692 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1693 static void VM_SV_AddStat(prvm_prog_t *prog)
1697 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1699 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1700 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1701 off = PRVM_G_INT (OFS_PARM2);
1710 VM_Warning(prog, "PF_SV_AddStat: unrecognized type %i - supported types are 1 (string up to 16 bytes, takes 4 stat slots), 2 (truncate to int32), 8 (send as float)", type);
1716 VM_Warning(prog, "PF_SV_AddStat: index (%i) may not be less than %i\n", i, MIN_VM_STAT);
1720 if (i >= MAX_CL_STATS)
1722 VM_Warning(prog, "PF_SV_AddStat: index (%i) >= MAX_CL_STATS (%i), not supported by protocol, and AddStat beyond MAX_VM_STAT (%i) conflicts with engine MOVEVARS\n", i, MAX_CL_STATS, MAX_VM_STAT);
1726 if (i > (MAX_CL_STATS - 4) && type == 1)
1728 VM_Warning(prog, "PF_SV_AddStat: index (%i) > (MAX_CL_STATS (%i) - 4) with string type won't fit in the protocol, and AddStat beyond MAX_VM_STAT conflicts with engine MOVEVARS\n", i, MAX_CL_STATS);
1732 // these are hazardous to override but sort of allowed if one wants to be adventurous... and enjoys warnings.
1733 if (i < MIN_VM_STAT)
1734 VM_Warning(prog, "PF_SV_AddStat: index (%i) < MIN_VM_STAT (%i) may conflict with engine stats - allowed, but this may break things\n", i, MIN_VM_STAT);
1735 else if (i >= MAX_VM_STAT && !sv_gameplayfix_customstats.integer)
1736 VM_Warning(prog, "PF_SV_AddStat: index (%i) >= MAX_VM_STAT (%i) conflicts with engine stats - allowed, but this may break slowmo and stuff\n", i, MAX_VM_STAT);
1737 else if (i > (MAX_VM_STAT - 4) && type == 1 && !sv_gameplayfix_customstats.integer)
1738 VM_Warning(prog, "PF_SV_AddStat: index (%i) >= MAX_VM_STAT (%i) - 4 with string type won't fit within MAX_VM_STAT, thus conflicting with engine stats - allowed, but this may break slowmo and stuff\n", i, MAX_VM_STAT);
1740 vm_customstats[i].type = type;
1741 vm_customstats[i].fieldoffset = off;
1742 if(vm_customstats_last < i)
1743 vm_customstats_last = i;
1750 copies data from one entity to another
1752 copyentity(src, dst)
1755 static void VM_SV_copyentity(prvm_prog_t *prog)
1757 prvm_edict_t *in, *out;
1758 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1759 in = PRVM_G_EDICT(OFS_PARM0);
1760 if (in == prog->edicts)
1762 VM_Warning(prog, "copyentity: can not read world entity\n");
1765 if (in->priv.server->free)
1767 VM_Warning(prog, "copyentity: can not read free entity\n");
1770 out = PRVM_G_EDICT(OFS_PARM1);
1771 if (out == prog->edicts)
1773 VM_Warning(prog, "copyentity: can not modify world entity\n");
1776 if (out->priv.server->free)
1778 VM_Warning(prog, "copyentity: can not modify free entity\n");
1781 memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
1782 if (VectorCompare(PRVM_serveredictvector(out, absmin), PRVM_serveredictvector(out, absmax)))
1792 sets the color of a client and broadcasts the update to all connected clients
1794 setcolor(clientent, value)
1797 static void VM_SV_setcolor(prvm_prog_t *prog)
1802 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1803 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1804 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1806 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1808 Con_Print("tried to setcolor a non-client\n");
1812 client = svs.clients + entnum-1;
1815 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1816 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1819 if (client->old_colors != client->colors)
1821 client->old_colors = client->colors;
1822 // send notification to all clients
1823 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1824 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1825 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1833 effect(origin, modelname, startframe, framecount, framerate)
1836 static void VM_SV_effect(prvm_prog_t *prog)
1841 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1842 s = PRVM_G_STRING(OFS_PARM1);
1845 VM_Warning(prog, "effect: no model specified\n");
1849 i = SV_ModelIndex(s, 1);
1852 VM_Warning(prog, "effect: model not precached\n");
1856 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1858 VM_Warning(prog, "effect: framecount < 1\n");
1862 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1864 VM_Warning(prog, "effect: framerate < 1\n");
1868 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1869 SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1872 static void VM_SV_te_blood(prvm_prog_t *prog)
1874 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1875 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1877 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1878 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1880 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1881 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1882 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1884 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1885 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1886 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1888 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1889 SV_FlushBroadcastMessages();
1892 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1894 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1895 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1897 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1898 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1900 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1910 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1911 SV_FlushBroadcastMessages();
1914 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1916 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1917 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1918 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1920 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1921 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1922 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1924 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1925 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1926 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1927 SV_FlushBroadcastMessages();
1930 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1932 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1933 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1935 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1936 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1942 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1943 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1944 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1948 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1950 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1952 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1953 // gravity true/false
1954 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1957 SV_FlushBroadcastMessages();
1960 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1962 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1963 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1965 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1966 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1970 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1972 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1973 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1974 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1976 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1977 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1978 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1980 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1982 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1983 SV_FlushBroadcastMessages();
1986 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1988 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1989 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1991 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1992 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1994 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1995 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1996 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1998 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1999 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2000 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2002 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2004 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2006 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2008 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2009 SV_FlushBroadcastMessages();
2012 static void VM_SV_te_spark(prvm_prog_t *prog)
2014 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
2015 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2017 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2018 MSG_WriteByte(&sv.datagram, TE_SPARK);
2020 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2021 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2022 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2024 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2025 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2026 MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2028 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2029 SV_FlushBroadcastMessages();
2032 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2034 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2035 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2036 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2038 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2039 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2040 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2041 SV_FlushBroadcastMessages();
2044 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2046 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2047 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2048 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2050 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2052 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2053 SV_FlushBroadcastMessages();
2056 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2058 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2059 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2060 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2062 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2063 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2064 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2065 SV_FlushBroadcastMessages();
2068 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2070 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2071 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2072 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2074 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2075 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2076 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2077 SV_FlushBroadcastMessages();
2080 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2082 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2083 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2084 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2086 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2087 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2088 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2089 SV_FlushBroadcastMessages();
2092 static void VM_SV_te_customflash(prvm_prog_t *prog)
2094 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2095 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2097 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2098 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2100 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2101 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2102 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2104 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2106 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2108 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2109 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2110 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2111 SV_FlushBroadcastMessages();
2114 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2116 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2117 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2118 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2120 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2121 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2122 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2123 SV_FlushBroadcastMessages();
2126 static void VM_SV_te_spike(prvm_prog_t *prog)
2128 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2129 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2130 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2132 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2133 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2134 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2135 SV_FlushBroadcastMessages();
2138 static void VM_SV_te_superspike(prvm_prog_t *prog)
2140 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2141 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2142 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2144 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2145 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2146 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2147 SV_FlushBroadcastMessages();
2150 static void VM_SV_te_explosion(prvm_prog_t *prog)
2152 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2153 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2154 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2156 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2157 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2158 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2159 SV_FlushBroadcastMessages();
2162 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2164 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2165 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2166 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2168 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2169 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2170 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2171 SV_FlushBroadcastMessages();
2174 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2176 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2177 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2178 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2180 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2181 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2182 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2183 SV_FlushBroadcastMessages();
2186 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2188 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2189 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2190 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2192 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2193 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2194 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2195 SV_FlushBroadcastMessages();
2198 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2200 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2201 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2202 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2204 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2205 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2206 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2207 SV_FlushBroadcastMessages();
2210 static void VM_SV_te_teleport(prvm_prog_t *prog)
2212 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2213 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2214 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2216 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2217 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2218 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2219 SV_FlushBroadcastMessages();
2222 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2224 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2225 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2226 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2229 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2230 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2232 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2233 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2234 SV_FlushBroadcastMessages();
2237 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2239 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2240 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2241 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2243 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2245 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2246 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2247 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2249 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2250 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2251 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2252 SV_FlushBroadcastMessages();
2255 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2257 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2258 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2259 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2261 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2263 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2264 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2265 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2267 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2268 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2269 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2270 SV_FlushBroadcastMessages();
2273 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2275 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2276 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2277 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2279 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2281 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2282 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2283 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2285 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2286 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2287 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2288 SV_FlushBroadcastMessages();
2291 static void VM_SV_te_beam(prvm_prog_t *prog)
2293 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2294 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2295 MSG_WriteByte(&sv.datagram, TE_BEAM);
2297 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2299 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2300 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2301 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2303 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2304 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2305 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2306 SV_FlushBroadcastMessages();
2309 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2311 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2312 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2313 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2314 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2315 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2316 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2317 SV_FlushBroadcastMessages();
2320 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2322 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2323 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2324 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2326 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2327 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2328 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2330 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2331 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2332 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2334 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2335 SV_FlushBroadcastMessages();
2338 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2339 //this function originally written by KrimZon, made shorter by LadyHavoc
2340 static void VM_SV_clientcommand(prvm_prog_t *prog)
2342 client_t *temp_client;
2344 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2346 //find client for this entity
2347 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2348 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2350 Con_Print("PF_clientcommand: entity is not a client\n");
2354 temp_client = host_client;
2355 host_client = svs.clients + i;
2356 Cmd_ExecuteString(&cmd_serverfromclient, PRVM_G_STRING(OFS_PARM1), src_client, true);
2357 host_client = temp_client;
2360 //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)
2361 static void VM_SV_setattachment(prvm_prog_t *prog)
2363 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2364 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2365 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2368 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2370 if (e == prog->edicts)
2372 VM_Warning(prog, "setattachment: can not modify world entity\n");
2375 if (e->priv.server->free)
2377 VM_Warning(prog, "setattachment: can not modify free entity\n");
2381 if (tagentity == NULL)
2382 tagentity = prog->edicts;
2386 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2388 model = SV_GetModelFromEdict(tagentity);
2391 tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2393 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);
2396 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));
2399 PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2400 PRVM_serveredictfloat(e, tag_index) = tagindex;
2403 /////////////////////////////////////////
2404 // DP_MD3_TAGINFO extension coded by VorteX
2406 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2410 i = (int)PRVM_serveredictfloat(e, modelindex);
2411 if (i < 1 || i >= MAX_MODELS)
2414 return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2417 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2424 Matrix4x4_CreateIdentity(tag_localmatrix);
2426 if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2428 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2439 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2442 float pitchsign = 1;
2444 scale = PRVM_serveredictfloat(ent, scale);
2449 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);
2452 pitchsign = SV_GetPitchSign(prog, ent);
2453 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);
2457 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2460 if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2462 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2463 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2464 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2465 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2467 *out = identitymatrix;
2471 // Warnings/errors code:
2472 // 0 - normal (everything all-right)
2475 // 3 - null or non-precached model
2476 // 4 - no tags with requested index
2477 // 5 - runaway loop at attachment chain
2478 extern cvar_t cl_bob;
2479 extern cvar_t cl_bobcycle;
2480 extern cvar_t cl_bobup;
2481 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2484 int modelindex, attachloop;
2485 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2488 *out = identitymatrix; // warnings and errors return identical matrix
2490 if (ent == prog->edicts)
2492 if (ent->priv.server->free)
2495 modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2496 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2499 model = SV_GetModelByIndex(modelindex);
2501 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2502 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2503 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2505 tagmatrix = identitymatrix;
2506 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2510 if (attachloop >= 256) // prevent runaway looping
2512 // apply transformation by child's tagindex on parent entity and then
2513 // by parent entity itself
2514 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2515 if (ret && attachloop == 0)
2517 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2518 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2519 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2520 // next iteration we process the parent entity
2521 if (PRVM_serveredictedict(ent, tag_entity))
2523 tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2524 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2531 // RENDER_VIEWMODEL magic
2532 if (PRVM_serveredictedict(ent, viewmodelforclient))
2534 Matrix4x4_Copy(&tagmatrix, out);
2535 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2537 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2538 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2541 // Cl_bob, ported from rendering code
2542 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2545 // LadyHavoc: this code is *weird*, but not replacable (I think it
2546 // should be done in QC on the server, but oh well, quake is quake)
2547 // LadyHavoc: figured out bobup: the time at which the sin is at 180
2548 // degrees (which allows lengthening or squishing the peak or valley)
2549 cycle = sv.time/cl_bobcycle.value;
2550 cycle -= (int)cycle;
2551 if (cycle < cl_bobup.value)
2552 cycle = sin(M_PI * cycle / cl_bobup.value);
2554 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2555 // bob is proportional to velocity in the xy plane
2556 // (don't count Z, or jumping messes it up)
2557 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;
2558 bob = bob*0.3 + bob*0.7*cycle;
2559 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2566 //float(entity ent, string tagname) gettagindex;
2568 static void VM_SV_gettagindex(prvm_prog_t *prog)
2571 const char *tag_name;
2574 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2576 ent = PRVM_G_EDICT(OFS_PARM0);
2577 tag_name = PRVM_G_STRING(OFS_PARM1);
2579 if (ent == prog->edicts)
2581 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2584 if (ent->priv.server->free)
2586 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2591 if (!SV_GetModelFromEdict(ent))
2592 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2595 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2597 if(developer_extra.integer)
2598 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2600 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2603 //vector(entity ent, float tagindex) gettaginfo;
2604 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2608 matrix4x4_t tag_matrix;
2609 matrix4x4_t tag_localmatrix;
2611 const char *tagname;
2613 vec3_t forward, left, up, origin;
2614 const dp_model_t *model;
2616 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2618 e = PRVM_G_EDICT(OFS_PARM0);
2619 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2621 returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2622 Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
2623 VectorCopy(forward, PRVM_serverglobalvector(v_forward));
2624 VectorNegate(left, PRVM_serverglobalvector(v_right));
2625 VectorCopy(up, PRVM_serverglobalvector(v_up));
2626 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2627 model = SV_GetModelFromEdict(e);
2628 VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2629 VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2630 VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2631 SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2632 Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
2634 PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2635 PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2636 VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
2637 VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
2638 VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2639 VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset));
2644 VM_Warning(prog, "gettagindex: can't affect world entity\n");
2647 VM_Warning(prog, "gettagindex: can't affect free entity\n");
2650 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2653 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2656 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2661 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2662 static void VM_SV_dropclient(prvm_prog_t *prog)
2665 client_t *oldhostclient;
2666 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2667 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2668 if (clientnum < 0 || clientnum >= svs.maxclients)
2670 VM_Warning(prog, "dropclient: not a client\n");
2673 if (!svs.clients[clientnum].active)
2675 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2678 oldhostclient = host_client;
2679 host_client = svs.clients + clientnum;
2680 SV_DropClient(false);
2681 host_client = oldhostclient;
2684 //entity() spawnclient (DP_SV_BOTCLIENT)
2685 static void VM_SV_spawnclient(prvm_prog_t *prog)
2689 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2690 prog->xfunction->builtinsprofile += 2;
2692 for (i = 0;i < svs.maxclients;i++)
2694 if (!svs.clients[i].active)
2696 prog->xfunction->builtinsprofile += 100;
2697 SV_ConnectClient (i, NULL);
2698 // this has to be set or else ClientDisconnect won't be called
2699 // we assume the qc will call ClientConnect...
2700 svs.clients[i].clientconnectcalled = true;
2701 ed = PRVM_EDICT_NUM(i + 1);
2705 VM_RETURN_EDICT(ed);
2708 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2709 static void VM_SV_clienttype(prvm_prog_t *prog)
2712 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2713 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2714 if (clientnum < 0 || clientnum >= svs.maxclients)
2715 PRVM_G_FLOAT(OFS_RETURN) = 3;
2716 else if (!svs.clients[clientnum].active)
2717 PRVM_G_FLOAT(OFS_RETURN) = 0;
2718 else if (svs.clients[clientnum].netconnection)
2719 PRVM_G_FLOAT(OFS_RETURN) = 1;
2721 PRVM_G_FLOAT(OFS_RETURN) = 2;
2728 string(string key) serverkey
2731 static void VM_SV_serverkey(prvm_prog_t *prog)
2733 char string[VM_STRINGTEMP_LENGTH];
2734 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2735 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2736 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2739 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2740 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2745 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2747 e = PRVM_G_EDICT(OFS_PARM0);
2748 if (e == prog->edicts)
2750 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2753 if (e->priv.server->free)
2755 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2758 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2759 if (i <= 0 || i >= MAX_MODELS)
2761 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2764 if (!sv.model_precache[i][0])
2766 VM_Warning(prog, "setmodelindex: model not precached\n");
2770 PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2771 PRVM_serveredictfloat(e, modelindex) = i;
2773 mod = SV_GetModelByIndex(i);
2777 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2778 SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2780 SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2783 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2786 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2787 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2790 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2792 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2794 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2795 if (i <= 0 || i >= MAX_MODELS)
2797 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2800 if (!sv.model_precache[i][0])
2802 VM_Warning(prog, "modelnameforindex: model not precached\n");
2806 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2809 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2810 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2813 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2814 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2817 PRVM_G_FLOAT(OFS_RETURN) = i;
2820 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2821 static void VM_SV_trailparticles(prvm_prog_t *prog)
2824 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2826 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2829 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2830 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2831 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2832 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start);
2833 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end);
2834 MSG_WriteVector(&sv.datagram, start, sv.protocol);
2835 MSG_WriteVector(&sv.datagram, end, sv.protocol);
2836 SV_FlushBroadcastMessages();
2839 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2840 static void VM_SV_pointparticles(prvm_prog_t *prog)
2842 int effectnum, count;
2844 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2846 if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2849 effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2850 VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2851 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2852 count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2853 if (count == 1 && !VectorLength2(vel))
2856 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2857 MSG_WriteShort(&sv.datagram, effectnum);
2858 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2862 // 1+2+12+12+2=29 bytes
2863 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2864 MSG_WriteShort(&sv.datagram, effectnum);
2865 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2866 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2867 MSG_WriteShort(&sv.datagram, count);
2870 SV_FlushBroadcastMessages();
2873 //PF_setpause, // void(float pause) setpause = #531;
2874 static void VM_SV_setpause(prvm_prog_t *prog) {
2876 pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2877 if (pauseValue != 0) { //pause the game
2879 sv.pausedstart = host.realtime;
2880 } else { //disable pause, in case it was enabled
2881 if (sv.paused != 0) {
2886 // send notification to all clients
2887 MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2888 MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2891 // #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.
2892 static void VM_SV_skel_create(prvm_prog_t *prog)
2894 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2895 dp_model_t *model = SV_GetModelByIndex(modelindex);
2896 skeleton_t *skeleton;
2898 PRVM_G_FLOAT(OFS_RETURN) = 0;
2899 if (!model || !model->num_bones)
2901 for (i = 0;i < MAX_EDICTS;i++)
2902 if (!prog->skeletons[i])
2904 if (i == MAX_EDICTS)
2906 prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(prog->progs_mempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2907 PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2908 skeleton->model = model;
2909 skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2910 // initialize to identity matrices
2911 for (i = 0;i < skeleton->model->num_bones;i++)
2912 skeleton->relativetransforms[i] = identitymatrix;
2915 // #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
2916 static void VM_SV_skel_build(prvm_prog_t *prog)
2918 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2919 skeleton_t *skeleton;
2920 prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2921 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2922 float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2923 int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2924 int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2925 dp_model_t *model = SV_GetModelByIndex(modelindex);
2929 framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2930 frameblend_t frameblend[MAX_FRAMEBLENDS];
2931 matrix4x4_t bonematrix;
2933 PRVM_G_FLOAT(OFS_RETURN) = 0;
2934 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2936 firstbone = max(0, firstbone);
2937 lastbone = min(lastbone, model->num_bones - 1);
2938 lastbone = min(lastbone, skeleton->model->num_bones - 1);
2939 VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2940 VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time);
2941 for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2943 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2945 memset(&bonematrix, 0, sizeof(bonematrix));
2946 for (blendindex = 0;blendindex < numblends;blendindex++)
2948 Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2949 Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp);
2951 Matrix4x4_Normalize3(&bonematrix, &bonematrix);
2952 Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac);
2954 PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2957 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2958 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
2960 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2961 skeleton_t *skeleton;
2962 PRVM_G_FLOAT(OFS_RETURN) = 0;
2963 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2965 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2968 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2969 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
2971 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2972 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2973 skeleton_t *skeleton;
2974 PRVM_G_INT(OFS_RETURN) = 0;
2975 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2977 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2979 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
2982 // #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)
2983 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
2985 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2986 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2987 skeleton_t *skeleton;
2988 PRVM_G_FLOAT(OFS_RETURN) = 0;
2989 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2991 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2993 PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2996 // #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
2997 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
2999 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3000 const char *tagname = PRVM_G_STRING(OFS_PARM1);
3001 skeleton_t *skeleton;
3002 PRVM_G_FLOAT(OFS_RETURN) = 0;
3003 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3005 PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
3008 // #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)
3009 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
3011 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3012 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3013 skeleton_t *skeleton;
3015 vec3_t forward, left, up, origin;
3016 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3017 VectorClear(PRVM_clientglobalvector(v_forward));
3018 VectorClear(PRVM_clientglobalvector(v_right));
3019 VectorClear(PRVM_clientglobalvector(v_up));
3020 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3022 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3024 matrix = skeleton->relativetransforms[bonenum];
3025 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3026 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3027 VectorNegate(left, PRVM_clientglobalvector(v_right));
3028 VectorCopy(up, PRVM_clientglobalvector(v_up));
3029 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3032 // #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)
3033 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
3035 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3036 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3037 skeleton_t *skeleton;
3040 vec3_t forward, left, up, origin;
3041 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3042 VectorClear(PRVM_clientglobalvector(v_forward));
3043 VectorClear(PRVM_clientglobalvector(v_right));
3044 VectorClear(PRVM_clientglobalvector(v_up));
3045 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3047 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3049 matrix = skeleton->relativetransforms[bonenum];
3050 // convert to absolute
3051 while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3054 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3056 Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3057 VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3058 VectorNegate(left, PRVM_clientglobalvector(v_right));
3059 VectorCopy(up, PRVM_clientglobalvector(v_up));
3060 VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3063 // #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)
3064 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3066 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3067 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3068 vec3_t forward, left, up, origin;
3069 skeleton_t *skeleton;
3071 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3073 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3075 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3076 VectorNegate(PRVM_clientglobalvector(v_right), left);
3077 VectorCopy(PRVM_clientglobalvector(v_up), up);
3078 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3079 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3080 skeleton->relativetransforms[bonenum] = matrix;
3083 // #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)
3084 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3086 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3087 int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3088 vec3_t forward, left, up, origin;
3089 skeleton_t *skeleton;
3092 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3094 if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3096 VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3097 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3098 VectorNegate(PRVM_clientglobalvector(v_right), left);
3099 VectorCopy(PRVM_clientglobalvector(v_up), up);
3100 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3101 temp = skeleton->relativetransforms[bonenum];
3102 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3105 // #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)
3106 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3108 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3109 int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3110 int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3112 vec3_t forward, left, up, origin;
3113 skeleton_t *skeleton;
3116 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3118 VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3119 VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3120 VectorNegate(PRVM_clientglobalvector(v_right), left);
3121 VectorCopy(PRVM_clientglobalvector(v_up), up);
3122 Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3123 firstbone = max(0, firstbone);
3124 lastbone = min(lastbone, skeleton->model->num_bones - 1);
3125 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3127 temp = skeleton->relativetransforms[bonenum];
3128 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3132 // #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
3133 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3135 int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3136 int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3137 int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3138 int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3140 skeleton_t *skeletondst;
3141 skeleton_t *skeletonsrc;
3142 if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3144 if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3146 firstbone = max(0, firstbone);
3147 lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3148 lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3149 for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3150 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3153 // #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)
3154 static void VM_SV_skel_delete(prvm_prog_t *prog)
3156 int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3157 skeleton_t *skeleton;
3158 if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3161 prog->skeletons[skeletonindex] = NULL;
3164 // #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
3165 static void VM_SV_frameforname(prvm_prog_t *prog)
3167 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3168 dp_model_t *model = SV_GetModelByIndex(modelindex);
3169 const char *name = PRVM_G_STRING(OFS_PARM1);
3171 PRVM_G_FLOAT(OFS_RETURN) = -1;
3172 if (!model || !model->animscenes)
3174 for (i = 0;i < model->numframes;i++)
3176 if (!strcasecmp(model->animscenes[i].name, name))
3178 PRVM_G_FLOAT(OFS_RETURN) = i;
3184 // #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.
3185 static void VM_SV_frameduration(prvm_prog_t *prog)
3187 int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3188 dp_model_t *model = SV_GetModelByIndex(modelindex);
3189 int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3190 PRVM_G_FLOAT(OFS_RETURN) = 0;
3191 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3193 if (model->animscenes[framenum].framerate)
3194 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3198 prvm_builtin_t vm_sv_builtins[] = {
3199 NULL, // #0 NULL function (not callable) (QUAKE)
3200 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3201 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3202 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3203 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3204 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3205 VM_break, // #6 void() break (QUAKE)
3206 VM_random, // #7 float() random (QUAKE)
3207 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3208 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3209 VM_error, // #10 void(string e) error (QUAKE)
3210 VM_objerror, // #11 void(string e) objerror (QUAKE)
3211 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3212 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3213 VM_spawn, // #14 entity() spawn (QUAKE)
3214 VM_remove, // #15 void(entity e) remove (QUAKE)
3215 VM_SV_traceline, // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3216 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
3217 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3218 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3219 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
3220 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3221 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3222 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
3223 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
3224 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3225 VM_ftos, // #26 string(float f) ftos (QUAKE)
3226 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3227 VM_coredump, // #28 void() coredump (QUAKE)
3228 VM_traceon, // #29 void() traceon (QUAKE)
3229 VM_traceoff, // #30 void() traceoff (QUAKE)
3230 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3231 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
3232 NULL, // #33 (QUAKE)
3233 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
3234 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3235 VM_rint, // #36 float(float v) rint (QUAKE)
3236 VM_floor, // #37 float(float v) floor (QUAKE)
3237 VM_ceil, // #38 float(float v) ceil (QUAKE)
3238 NULL, // #39 (QUAKE)
3239 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3240 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3241 NULL, // #42 (QUAKE)
3242 VM_fabs, // #43 float(float f) fabs (QUAKE)
3243 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
3244 VM_cvar, // #45 float(string s) cvar (QUAKE)
3245 VM_localcmd_server, // #46 void(string s) localcmd (QUAKE)
3246 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3247 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3248 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3249 NULL, // #50 (QUAKE)
3250 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3251 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
3252 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
3253 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
3254 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
3255 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
3256 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
3257 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
3258 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
3259 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3260 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3261 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3262 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3263 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3264 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3265 NULL, // #66 (QUAKE)
3266 VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
3267 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3268 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
3269 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
3270 NULL, // #71 (QUAKE)
3271 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3272 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
3273 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3274 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3275 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3276 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3277 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
3278 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3279 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3280 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3281 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3282 NULL, // #83 (QUAKE)
3283 NULL, // #84 (QUAKE)
3284 NULL, // #85 (QUAKE)
3285 NULL, // #86 (QUAKE)
3286 NULL, // #87 (QUAKE)
3287 NULL, // #88 (QUAKE)
3288 NULL, // #89 (QUAKE)
3289 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3290 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3291 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3292 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3293 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3294 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3295 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3296 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3297 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3298 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3299 // FrikaC and Telejano range #100-#199
3310 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3311 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3312 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3313 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3314 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3315 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3316 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3317 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3318 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3319 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3400 // FTEQW range #200-#299
3419 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3422 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3423 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3424 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3425 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3426 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3427 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3428 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3429 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3430 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3431 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3433 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3441 VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
3464 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.
3465 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
3466 VM_SV_skel_get_numbones, // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3467 VM_SV_skel_get_bonename, // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3468 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)
3469 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
3470 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)
3471 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)
3472 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)
3473 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)
3474 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)
3475 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
3476 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)
3477 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
3478 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.
3501 // CSQC range #300-#399
3502 NULL, // #300 void() clearscene (EXT_CSQC)
3503 NULL, // #301 void(float mask) addentities (EXT_CSQC)
3504 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
3505 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
3506 NULL, // #304 void() renderscene (EXT_CSQC)
3507 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3508 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3509 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3510 NULL, // #308 void() R_EndPolygon
3512 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3513 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
3517 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3518 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
3519 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3520 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3521 NULL, // #319 void(string name) freepic (EXT_CSQC)
3522 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3523 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3524 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3525 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3526 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
3527 NULL, // #325 void(void) drawresetcliparea
3532 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
3533 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
3534 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
3535 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3536 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3537 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3538 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3539 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3540 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
3541 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3542 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3543 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3544 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3545 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3546 NULL, // #344 vector() getmousepos (EXT_CSQC)
3547 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3548 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3549 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3550 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3551 NULL, // #349 float() isdemo (EXT_CSQC)
3552 VM_isserver, // #350 float() isserver (EXT_CSQC)
3553 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3554 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3555 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3556 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3562 NULL, // #360 float() readbyte (EXT_CSQC)
3563 NULL, // #361 float() readchar (EXT_CSQC)
3564 NULL, // #362 float() readshort (EXT_CSQC)
3565 NULL, // #363 float() readlong (EXT_CSQC)
3566 NULL, // #364 float() readcoord (EXT_CSQC)
3567 NULL, // #365 float() readangle (EXT_CSQC)
3568 NULL, // #366 string() readstring (EXT_CSQC)
3569 NULL, // #367 float() readfloat (EXT_CSQC)
3602 // LadyHavoc's range #400-#499
3603 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3604 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3605 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3606 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3607 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3608 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3609 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3610 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3611 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)
3612 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3613 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3614 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3615 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3616 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3617 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3618 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3619 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3620 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3621 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3622 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3623 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3624 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3625 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3626 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3627 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3628 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3629 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3630 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3631 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3632 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3633 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3634 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3635 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3636 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3637 VM_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3638 VM_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3639 VM_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3640 VM_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3641 VM_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3642 VM_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3643 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3644 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3645 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3646 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3647 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3648 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3649 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3650 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3651 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3652 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3653 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3654 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3655 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3656 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3657 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3658 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3659 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3660 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3662 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3663 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3664 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3665 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3666 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3667 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3668 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3669 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3670 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3671 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3672 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3674 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3675 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3676 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3677 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3678 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3679 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3680 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3681 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3682 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3683 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3684 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3685 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3686 VM_SV_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3687 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3688 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3689 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3697 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3698 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3699 VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3700 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3701 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3702 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3703 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3704 VM_SV_WritePicture, // #501
3706 VM_whichpack, // #503 string(string) whichpack = #503;
3713 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3714 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3715 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3716 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)
3717 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3718 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3719 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3720 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3721 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3722 VM_gettime, // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3732 VM_loadfromdata, // #529
3733 VM_loadfromfile, // #530
3734 VM_SV_setpause, // #531 void(float pause) setpause = #531;
3736 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3737 VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3738 VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP)
3739 VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP)
3740 VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP)
3741 VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP)
3743 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE)
3744 VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE)
3745 VM_physics_addtorque, // #542 void(entity e, vector torque) physics_addtorque = #542; (DP_PHYSICS_ODE)
3808 VM_callfunction, // #605
3809 VM_writetofile, // #606
3810 VM_isfunction, // #607
3816 VM_parseentitydata, // #613
3827 VM_SV_getextresponse, // #624 string getextresponse(void)
3830 VM_sprintf, // #627 string sprintf(string format, ...)
3831 VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3832 VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3842 VM_digest_hex, // #639
3845 VM_coverage, // #642
3849 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3851 void SVVM_init_cmd(prvm_prog_t *prog)
3856 void SVVM_reset_cmd(prvm_prog_t *prog)
3858 World_End(&sv.world);
3860 if(prog->loaded && PRVM_serverfunction(SV_Shutdown))
3862 func_t s = PRVM_serverfunction(SV_Shutdown);
3863 PRVM_serverglobalfloat(time) = sv.time;
3864 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3865 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");