3 //============================================================================
6 #define PF_WARNING(s) do{Con_Printf(s);PRVM_PrintState();return;}while(0)
7 cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2"}; //"0.93"}; // LordHavoc: disabled autoaim by default
10 char *vm_sv_extensions =
12 "DP_CON_ALIASPARAMETERS "
30 "DP_ENT_CUSTOMCOLORMAP "
31 "DP_ENT_EXTERIORMODELTOCLIENT "
33 "DP_ENT_LOWPRECISION "
36 "DP_GFX_EXTERNALTEXTURES "
38 "DP_GFX_QUAKE3MODELTAGS "
42 "DP_HALFLIFE_MAP_CVAR "
48 "DP_MOVETYPEBOUNCEMISSILE "
55 "DP_QC_FINDCHAINFLAGS "
56 "DP_QC_FINDCHAINFLOAT "
59 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
64 "DP_QC_MULTIPLETEMPSTRINGS "
66 "DP_QC_SINCOSSQRTPOW "
69 "DP_QC_TRACE_MOVETYPE_HITMODEL "
70 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
71 "DP_QC_VECTORVECTORS "
77 "DP_SND_DIRECTIONLESSATTNNONE "
86 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
87 "DP_SV_DRAWONLYTOCLIENT "
90 "DP_SV_NODRAWTOCLIENT "
92 "DP_SV_PLAYERPHYSICS "
93 "DP_SV_PRECACHEANYTIME "
95 "DP_SV_ROTATINGBMODEL "
98 "DP_SV_WRITEUNTERMINATEDSTRING "
102 "DP_TE_EXPLOSIONRGB "
104 "DP_TE_PARTICLECUBE "
105 "DP_TE_PARTICLERAIN "
106 "DP_TE_PARTICLESNOW "
108 "DP_TE_QUADEFFECTS1 "
111 "DP_TE_STANDARDEFFECTBUILTINS "
114 "KRIMZON_SV_PARSECLIENTCOMMAND "
118 "PRYDON_CLIENTCURSOR "
119 "TENEBRAE_GFX_DLIGHTS "
121 "NEXUIZ_PLAYERMODEL "
128 Writes new values for v_forward, v_up, and v_right based on angles
132 void PF_makevectors (void)
134 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
141 Writes new values for v_forward, v_up, and v_right based on the given forward vector
142 vectorvectors(vector, vector)
145 void PF_vectorvectors (void)
147 VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward);
148 VectorVectors(prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
155 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.
157 setorigin (entity, origin)
160 void PF_setorigin (void)
165 e = PRVM_G_EDICT(OFS_PARM0);
166 if (e == prog->edicts)
167 PF_WARNING("setorigin: can not modify world entity\n");
168 if (e->priv.server->free)
169 PF_WARNING("setorigin: can not modify free entity\n");
170 org = PRVM_G_VECTOR(OFS_PARM1);
171 VectorCopy (org, e->fields.server->origin);
172 SV_LinkEdict (e, false);
176 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
180 for (i=0 ; i<3 ; i++)
182 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
184 // set derived values
185 VectorCopy (min, e->fields.server->mins);
186 VectorCopy (max, e->fields.server->maxs);
187 VectorSubtract (max, min, e->fields.server->size);
189 SV_LinkEdict (e, false);
196 the size box is rotated by the current angle
197 LordHavoc: no it isn't...
199 setsize (entity, minvector, maxvector)
202 void PF_setsize (void)
207 e = PRVM_G_EDICT(OFS_PARM0);
208 if (e == prog->edicts)
209 PF_WARNING("setsize: can not modify world entity\n");
210 if (e->priv.server->free)
211 PF_WARNING("setsize: can not modify free entity\n");
212 min = PRVM_G_VECTOR(OFS_PARM1);
213 max = PRVM_G_VECTOR(OFS_PARM2);
214 SetMinMaxSize (e, min, max, false);
222 setmodel(entity, model)
225 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
226 void PF_setmodel (void)
232 e = PRVM_G_EDICT(OFS_PARM0);
233 if (e == prog->edicts)
234 PF_WARNING("setmodel: can not modify world entity\n");
235 if (e->priv.server->free)
236 PF_WARNING("setmodel: can not modify free entity\n");
237 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
238 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
239 e->fields.server->modelindex = i;
245 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
246 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
248 SetMinMaxSize (e, quakemins, quakemaxs, true);
251 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
258 single print to a specific client
260 sprint(clientent, value)
263 void PF_sprint (void)
267 char string[VM_STRINGTEMP_LENGTH];
269 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
271 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
273 Con_Print("tried to sprint to a non-client\n");
277 client = svs.clients + entnum-1;
278 VM_VarString(1, string, sizeof(string));
279 MSG_WriteChar(&client->message,svc_print);
280 MSG_WriteString(&client->message, string);
288 single print to a specific client
290 centerprint(clientent, value)
293 void PF_centerprint (void)
297 char string[VM_STRINGTEMP_LENGTH];
299 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
301 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
303 Con_Print("tried to sprint to a non-client\n");
307 client = svs.clients + entnum-1;
308 VM_VarString(1, string, sizeof(string));
309 MSG_WriteChar(&client->message,svc_centerprint);
310 MSG_WriteString(&client->message, string);
317 particle(origin, color, count)
320 void PF_particle (void)
326 org = PRVM_G_VECTOR(OFS_PARM0);
327 dir = PRVM_G_VECTOR(OFS_PARM1);
328 color = PRVM_G_FLOAT(OFS_PARM2);
329 count = PRVM_G_FLOAT(OFS_PARM3);
330 SV_StartParticle (org, dir, color, count);
340 void PF_ambientsound (void)
344 float vol, attenuation;
347 pos = PRVM_G_VECTOR (OFS_PARM0);
348 samp = PRVM_G_STRING(OFS_PARM1);
349 vol = PRVM_G_FLOAT(OFS_PARM2);
350 attenuation = PRVM_G_FLOAT(OFS_PARM3);
352 // check to see if samp was properly precached
353 soundnum = SV_SoundIndex(samp, 1);
361 // add an svc_spawnambient command to the level signon packet
364 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
366 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
368 MSG_WriteVector(&sv.signon, pos, sv.protocol);
371 MSG_WriteShort (&sv.signon, soundnum);
373 MSG_WriteByte (&sv.signon, soundnum);
375 MSG_WriteByte (&sv.signon, vol*255);
376 MSG_WriteByte (&sv.signon, attenuation*64);
384 Each entity can have eight independant sound sources, like voice,
387 Channel 0 is an auto-allocate channel, the others override anything
388 already running on that entity/channel pair.
390 An attenuation of 0 will play full volume everywhere in the level.
391 Larger attenuations will drop off.
399 prvm_edict_t *entity;
403 entity = PRVM_G_EDICT(OFS_PARM0);
404 channel = PRVM_G_FLOAT(OFS_PARM1);
405 sample = PRVM_G_STRING(OFS_PARM2);
406 volume = PRVM_G_FLOAT(OFS_PARM3) * 255;
407 attenuation = PRVM_G_FLOAT(OFS_PARM4);
409 if (volume < 0 || volume > 255)
410 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
412 if (attenuation < 0 || attenuation > 4)
413 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
415 if (channel < 0 || channel > 7)
416 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
418 SV_StartSound (entity, channel, sample, volume, attenuation);
425 Used for use tracing and shot targeting
426 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
427 if the tryents flag is set.
429 traceline (vector1, vector2, tryents)
432 void PF_traceline (void)
439 prog->xfunction->builtinsprofile += 30;
441 v1 = PRVM_G_VECTOR(OFS_PARM0);
442 v2 = PRVM_G_VECTOR(OFS_PARM1);
443 move = PRVM_G_FLOAT(OFS_PARM2);
444 ent = PRVM_G_EDICT(OFS_PARM3);
446 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
448 prog->globals.server->trace_allsolid = trace.allsolid;
449 prog->globals.server->trace_startsolid = trace.startsolid;
450 prog->globals.server->trace_fraction = trace.fraction;
451 prog->globals.server->trace_inwater = trace.inwater;
452 prog->globals.server->trace_inopen = trace.inopen;
453 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
454 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
455 prog->globals.server->trace_plane_dist = trace.plane.dist;
457 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
459 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
460 // FIXME: add trace_endcontents
468 Used for use tracing and shot targeting
469 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
470 if the tryents flag is set.
472 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
475 // LordHavoc: added this for my own use, VERY useful, similar to traceline
476 void PF_tracebox (void)
478 float *v1, *v2, *m1, *m2;
483 prog->xfunction->builtinsprofile += 30;
485 v1 = PRVM_G_VECTOR(OFS_PARM0);
486 m1 = PRVM_G_VECTOR(OFS_PARM1);
487 m2 = PRVM_G_VECTOR(OFS_PARM2);
488 v2 = PRVM_G_VECTOR(OFS_PARM3);
489 move = PRVM_G_FLOAT(OFS_PARM4);
490 ent = PRVM_G_EDICT(OFS_PARM5);
492 trace = SV_Move (v1, m1, m2, v2, move, ent);
494 prog->globals.server->trace_allsolid = trace.allsolid;
495 prog->globals.server->trace_startsolid = trace.startsolid;
496 prog->globals.server->trace_fraction = trace.fraction;
497 prog->globals.server->trace_inwater = trace.inwater;
498 prog->globals.server->trace_inopen = trace.inopen;
499 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
500 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
501 prog->globals.server->trace_plane_dist = trace.plane.dist;
503 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
505 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
508 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
509 void PF_tracetoss (void)
513 prvm_edict_t *ignore;
515 prog->xfunction->builtinsprofile += 600;
517 ent = PRVM_G_EDICT(OFS_PARM0);
518 if (ent == prog->edicts)
519 PF_WARNING("tracetoss: can not use world entity\n");
520 ignore = PRVM_G_EDICT(OFS_PARM1);
522 trace = SV_Trace_Toss (ent, ignore);
524 prog->globals.server->trace_allsolid = trace.allsolid;
525 prog->globals.server->trace_startsolid = trace.startsolid;
526 prog->globals.server->trace_fraction = trace.fraction;
527 prog->globals.server->trace_inwater = trace.inwater;
528 prog->globals.server->trace_inopen = trace.inopen;
529 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
530 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
531 prog->globals.server->trace_plane_dist = trace.plane.dist;
533 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
535 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
543 Returns true if the given entity can move to the given position from it's
544 current position by walking or rolling.
546 scalar checkpos (entity, vector)
549 void PF_checkpos (void)
553 //============================================================================
556 unsigned char checkpvs[MAX_MAP_LEAFS/8];
558 int PF_newcheckclient (int check)
564 // cycle to the next one
566 check = bound(1, check, svs.maxclients);
567 if (check == svs.maxclients)
575 prog->xfunction->builtinsprofile++;
577 if (i == svs.maxclients+1)
579 // look up the client's edict
580 ent = PRVM_EDICT_NUM(i);
581 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
582 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
584 // found a valid client (possibly the same one again)
588 // get the PVS for the entity
589 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
591 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
592 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
601 Returns a client (or object that has a client enemy) that would be a
604 If there is more than one valid option, they are cycled each frame
606 If (self.origin + self.viewofs) is not in the PVS of the current target,
607 it is not returned at all.
612 int c_invis, c_notvis;
613 void PF_checkclient (void)
615 prvm_edict_t *ent, *self;
618 // find a new check if on a new frame
619 if (sv.time - sv.lastchecktime >= 0.1)
621 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
622 sv.lastchecktime = sv.time;
625 // return check if it might be visible
626 ent = PRVM_EDICT_NUM(sv.lastcheck);
627 if (ent->priv.server->free || ent->fields.server->health <= 0)
629 VM_RETURN_EDICT(prog->edicts);
633 // if current entity can't possibly see the check entity, return 0
634 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
635 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
636 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
639 VM_RETURN_EDICT(prog->edicts);
643 // might be able to see it
645 VM_RETURN_EDICT(ent);
648 //============================================================================
655 Sends text over to the client's execution buffer
657 stuffcmd (clientent, value, ...)
660 void PF_stuffcmd (void)
664 char string[VM_STRINGTEMP_LENGTH];
666 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
667 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
669 Con_Print("Can't stuffcmd to a non-client\n");
673 VM_VarString(1, string, sizeof(string));
676 host_client = svs.clients + entnum-1;
677 Host_ClientCommands ("%s", string);
685 Returns a chain of entities that have origins within a spherical area
687 findradius (origin, radius)
690 void PF_findradius (void)
692 prvm_edict_t *ent, *chain;
693 vec_t radius, radius2;
694 vec3_t org, eorg, mins, maxs;
697 prvm_edict_t *touchedicts[MAX_EDICTS];
699 chain = (prvm_edict_t *)prog->edicts;
701 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
702 radius = PRVM_G_FLOAT(OFS_PARM1);
703 radius2 = radius * radius;
705 mins[0] = org[0] - (radius + 1);
706 mins[1] = org[1] - (radius + 1);
707 mins[2] = org[2] - (radius + 1);
708 maxs[0] = org[0] + (radius + 1);
709 maxs[1] = org[1] + (radius + 1);
710 maxs[2] = org[2] + (radius + 1);
711 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
712 if (numtouchedicts > MAX_EDICTS)
714 // this never happens
715 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
716 numtouchedicts = MAX_EDICTS;
718 for (i = 0;i < numtouchedicts;i++)
720 ent = touchedicts[i];
721 prog->xfunction->builtinsprofile++;
722 // Quake did not return non-solid entities but darkplaces does
723 // (note: this is the reason you can't blow up fallen zombies)
724 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
726 // LordHavoc: compare against bounding box rather than center so it
727 // doesn't miss large objects, and use DotProduct instead of Length
728 // for a major speedup
729 VectorSubtract(org, ent->fields.server->origin, eorg);
730 if (sv_gameplayfix_findradiusdistancetobox.integer)
732 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
733 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
734 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
737 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
738 if (DotProduct(eorg, eorg) < radius2)
740 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
745 VM_RETURN_EDICT(chain);
748 void PF_precache_file (void)
749 { // precache_file is only used to copy files with qcc, it does nothing
750 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
754 void PF_precache_sound (void)
756 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
757 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
760 void PF_precache_model (void)
762 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
763 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
770 float(float yaw, float dist) walkmove
773 void PF_walkmove (void)
781 // assume failure if it returns early
782 PRVM_G_FLOAT(OFS_RETURN) = 0;
784 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
785 if (ent == prog->edicts)
786 PF_WARNING("walkmove: can not modify world entity\n");
787 if (ent->priv.server->free)
788 PF_WARNING("walkmove: can not modify free entity\n");
789 yaw = PRVM_G_FLOAT(OFS_PARM0);
790 dist = PRVM_G_FLOAT(OFS_PARM1);
792 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
795 yaw = yaw*M_PI*2 / 360;
797 move[0] = cos(yaw)*dist;
798 move[1] = sin(yaw)*dist;
801 // save program state, because SV_movestep may call other progs
802 oldf = prog->xfunction;
803 oldself = prog->globals.server->self;
805 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
808 // restore program state
809 prog->xfunction = oldf;
810 prog->globals.server->self = oldself;
820 void PF_droptofloor (void)
826 // assume failure if it returns early
827 PRVM_G_FLOAT(OFS_RETURN) = 0;
829 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
830 if (ent == prog->edicts)
831 PF_WARNING("droptofloor: can not modify world entity\n");
832 if (ent->priv.server->free)
833 PF_WARNING("droptofloor: can not modify free entity\n");
835 VectorCopy (ent->fields.server->origin, end);
838 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
840 if (trace.fraction != 1)
842 VectorCopy (trace.endpos, ent->fields.server->origin);
843 SV_LinkEdict (ent, false);
844 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
845 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
846 PRVM_G_FLOAT(OFS_RETURN) = 1;
847 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
848 ent->priv.server->suspendedinairflag = true;
856 void(float style, string value) lightstyle
859 void PF_lightstyle (void)
866 style = PRVM_G_FLOAT(OFS_PARM0);
867 val = PRVM_G_STRING(OFS_PARM1);
869 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
870 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
873 // change the string in sv
874 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
876 // send message to all clients on this server
877 if (sv.state != ss_active)
880 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
884 MSG_WriteChar (&client->message, svc_lightstyle);
885 MSG_WriteChar (&client->message,style);
886 MSG_WriteString (&client->message, val);
896 void PF_checkbottom (void)
898 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
906 void PF_pointcontents (void)
908 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
915 Pick a vector for the player to shoot along
916 vector aim(entity, missilespeed)
921 prvm_edict_t *ent, *check, *bestent;
922 vec3_t start, dir, end, bestdir;
925 float dist, bestdist;
928 // assume failure if it returns early
929 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
930 // if sv_aim is so high it can't possibly accept anything, skip out early
931 if (sv_aim.value >= 1)
934 ent = PRVM_G_EDICT(OFS_PARM0);
935 if (ent == prog->edicts)
936 PF_WARNING("aim: can not use world entity\n");
937 if (ent->priv.server->free)
938 PF_WARNING("aim: can not use free entity\n");
939 speed = PRVM_G_FLOAT(OFS_PARM1);
941 VectorCopy (ent->fields.server->origin, start);
944 // try sending a trace straight
945 VectorCopy (prog->globals.server->v_forward, dir);
946 VectorMA (start, 2048, dir, end);
947 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
948 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
949 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
951 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
956 // try all possible entities
957 VectorCopy (dir, bestdir);
958 bestdist = sv_aim.value;
961 check = PRVM_NEXT_EDICT(prog->edicts);
962 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
964 prog->xfunction->builtinsprofile++;
965 if (check->fields.server->takedamage != DAMAGE_AIM)
969 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
970 continue; // don't aim at teammate
971 for (j=0 ; j<3 ; j++)
972 end[j] = check->fields.server->origin[j]
973 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
974 VectorSubtract (end, start, dir);
975 VectorNormalize (dir);
976 dist = DotProduct (dir, prog->globals.server->v_forward);
978 continue; // to far to turn
979 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
981 { // can shoot at this one
989 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
990 dist = DotProduct (dir, prog->globals.server->v_forward);
991 VectorScale (prog->globals.server->v_forward, dist, end);
993 VectorNormalize (end);
994 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
998 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1006 This was a major timewaster in progs, so it was converted to C
1009 void PF_changeyaw (void)
1012 float ideal, current, move, speed;
1014 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1015 if (ent == prog->edicts)
1016 PF_WARNING("changeyaw: can not modify world entity\n");
1017 if (ent->priv.server->free)
1018 PF_WARNING("changeyaw: can not modify free entity\n");
1019 current = ANGLEMOD(ent->fields.server->angles[1]);
1020 ideal = ent->fields.server->ideal_yaw;
1021 speed = ent->fields.server->yaw_speed;
1023 if (current == ideal)
1025 move = ideal - current;
1026 if (ideal > current)
1047 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1055 void PF_changepitch (void)
1058 float ideal, current, move, speed;
1061 ent = PRVM_G_EDICT(OFS_PARM0);
1062 if (ent == prog->edicts)
1063 PF_WARNING("changepitch: can not modify world entity\n");
1064 if (ent->priv.server->free)
1065 PF_WARNING("changepitch: can not modify free entity\n");
1066 current = ANGLEMOD( ent->fields.server->angles[0] );
1067 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1068 ideal = val->_float;
1071 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1074 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1075 speed = val->_float;
1078 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1082 if (current == ideal)
1084 move = ideal - current;
1085 if (ideal > current)
1106 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1110 ===============================================================================
1114 ===============================================================================
1117 #define MSG_BROADCAST 0 // unreliable to all
1118 #define MSG_ONE 1 // reliable to one (msg_entity)
1119 #define MSG_ALL 2 // reliable to all
1120 #define MSG_INIT 3 // write to the init string
1122 sizebuf_t *WriteDest (void)
1128 dest = PRVM_G_FLOAT(OFS_PARM0);
1132 return &sv.datagram;
1135 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1136 entnum = PRVM_NUM_FOR_EDICT(ent);
1137 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1139 Con_Printf ("WriteDest: tried to write to non-client\n");
1140 return &sv.reliable_datagram;
1143 return &svs.clients[entnum-1].message;
1146 Con_Printf ("WriteDest: bad destination\n");
1148 return &sv.reliable_datagram;
1157 void PF_WriteByte (void)
1159 MSG_WriteByte (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1162 void PF_WriteChar (void)
1164 MSG_WriteChar (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1167 void PF_WriteShort (void)
1169 MSG_WriteShort (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1172 void PF_WriteLong (void)
1174 MSG_WriteLong (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1177 void PF_WriteAngle (void)
1179 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1182 void PF_WriteCoord (void)
1184 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1187 void PF_WriteString (void)
1189 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1192 void PF_WriteUnterminatedString (void)
1194 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1198 void PF_WriteEntity (void)
1200 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1203 //////////////////////////////////////////////////////////
1205 void PF_makestatic (void)
1210 ent = PRVM_G_EDICT(OFS_PARM0);
1211 if (ent == prog->edicts)
1212 PF_WARNING("makestatic: can not modify world entity\n");
1213 if (ent->priv.server->free)
1214 PF_WARNING("makestatic: can not modify free entity\n");
1217 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1222 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1223 MSG_WriteShort (&sv.signon, ent->fields.server->modelindex);
1224 MSG_WriteShort (&sv.signon, ent->fields.server->frame);
1228 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1229 MSG_WriteByte (&sv.signon, ent->fields.server->modelindex);
1230 MSG_WriteByte (&sv.signon, ent->fields.server->frame);
1233 MSG_WriteByte (&sv.signon, ent->fields.server->colormap);
1234 MSG_WriteByte (&sv.signon, ent->fields.server->skin);
1235 for (i=0 ; i<3 ; i++)
1237 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1238 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1241 // throw the entity away now
1245 //=============================================================================
1252 void PF_setspawnparms (void)
1258 ent = PRVM_G_EDICT(OFS_PARM0);
1259 i = PRVM_NUM_FOR_EDICT(ent);
1260 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1262 Con_Print("tried to setspawnparms on a non-client\n");
1266 // copy spawn parms out of the client_t
1267 client = svs.clients + i-1;
1268 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1269 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1276 Returns a color vector indicating the lighting at the requested point.
1278 (Internal Operation note: actually measures the light beneath the point, just like
1279 the model lighting on the client)
1284 void PF_getlight (void)
1286 vec3_t ambientcolor, diffusecolor, diffusenormal;
1288 p = PRVM_G_VECTOR(OFS_PARM0);
1289 VectorClear(ambientcolor);
1290 VectorClear(diffusecolor);
1291 VectorClear(diffusenormal);
1292 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1293 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1294 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1297 void PF_registercvar (void)
1299 const char *name, *value;
1300 name = PRVM_G_STRING(OFS_PARM0);
1301 value = PRVM_G_STRING(OFS_PARM1);
1302 PRVM_G_FLOAT(OFS_RETURN) = 0;
1304 // first check to see if it has already been defined
1305 if (Cvar_FindVar (name))
1308 // check for overlap with a command
1309 if (Cmd_Exists (name))
1311 Con_Printf("PF_registercvar: %s is a command\n", name);
1315 Cvar_Get(name, value, 0);
1317 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1324 copies data from one entity to another
1326 copyentity(src, dst)
1329 void PF_copyentity (void)
1331 prvm_edict_t *in, *out;
1332 in = PRVM_G_EDICT(OFS_PARM0);
1333 if (in == prog->edicts)
1334 PF_WARNING("copyentity: can not read world entity\n");
1335 if (in->priv.server->free)
1336 PF_WARNING("copyentity: can not read free entity\n");
1337 out = PRVM_G_EDICT(OFS_PARM1);
1338 if (out == prog->edicts)
1339 PF_WARNING("copyentity: can not modify world entity\n");
1340 if (out->priv.server->free)
1341 PF_WARNING("copyentity: can not modify free entity\n");
1342 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1350 sets the color of a client and broadcasts the update to all connected clients
1352 setcolor(clientent, value)
1355 void PF_setcolor (void)
1361 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1362 i = PRVM_G_FLOAT(OFS_PARM1);
1364 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1366 Con_Print("tried to setcolor a non-client\n");
1370 client = svs.clients + entnum-1;
1373 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1375 client->edict->fields.server->team = (i & 15) + 1;
1378 if (client->old_colors != client->colors)
1380 client->old_colors = client->colors;
1381 // send notification to all clients
1382 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1383 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1384 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1392 effect(origin, modelname, startframe, framecount, framerate)
1395 void PF_effect (void)
1399 s = PRVM_G_STRING(OFS_PARM1);
1401 PF_WARNING("effect: no model specified\n");
1403 i = SV_ModelIndex(s, 1);
1405 PF_WARNING("effect: model not precached\n");
1406 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
1409 void PF_te_blood (void)
1411 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1413 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1414 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1416 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1417 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1418 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1420 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1421 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1422 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1424 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1427 void PF_te_bloodshower (void)
1429 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1431 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1432 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1434 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1435 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1436 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1438 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1439 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1440 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1442 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1444 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1447 void PF_te_explosionrgb (void)
1449 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1450 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1452 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1453 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1454 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1456 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1457 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1458 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1461 void PF_te_particlecube (void)
1463 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1465 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1466 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1468 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1469 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1470 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1472 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1473 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1474 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1476 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1477 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1478 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1480 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1482 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1483 // gravity true/false
1484 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1486 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1489 void PF_te_particlerain (void)
1491 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1493 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1494 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1496 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1497 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1498 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1500 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1501 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1502 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1504 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1505 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1506 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1508 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1510 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1513 void PF_te_particlesnow (void)
1515 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1517 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1518 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1520 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1521 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1522 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1524 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1525 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1526 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1528 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1529 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1530 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1532 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1534 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1537 void PF_te_spark (void)
1539 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1541 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1542 MSG_WriteByte(&sv.datagram, TE_SPARK);
1544 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1545 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1546 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1548 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1549 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1550 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1552 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1555 void PF_te_gunshotquad (void)
1557 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1558 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1560 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1561 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1562 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1565 void PF_te_spikequad (void)
1567 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1568 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1570 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1571 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1572 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1575 void PF_te_superspikequad (void)
1577 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1578 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1580 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1581 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1582 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1585 void PF_te_explosionquad (void)
1587 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1588 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1590 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1591 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1592 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1595 void PF_te_smallflash (void)
1597 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1598 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1600 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1601 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1602 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1605 void PF_te_customflash (void)
1607 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1609 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1610 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1612 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1613 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1614 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1616 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1618 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1620 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1621 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1622 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1625 void PF_te_gunshot (void)
1627 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1628 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1630 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1631 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1632 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1635 void PF_te_spike (void)
1637 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1638 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1640 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1641 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1642 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1645 void PF_te_superspike (void)
1647 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1648 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1650 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1651 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1652 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1655 void PF_te_explosion (void)
1657 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1658 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1660 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1661 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1662 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1665 void PF_te_tarexplosion (void)
1667 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1668 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1670 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1671 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1672 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1675 void PF_te_wizspike (void)
1677 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1678 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1680 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1681 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1682 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1685 void PF_te_knightspike (void)
1687 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1688 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1690 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1691 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1692 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1695 void PF_te_lavasplash (void)
1697 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1698 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1700 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1701 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1702 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1705 void PF_te_teleport (void)
1707 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1708 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1710 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1711 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1712 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1715 void PF_te_explosion2 (void)
1717 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1718 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1720 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1721 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1722 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1724 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM1));
1725 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1728 void PF_te_lightning1 (void)
1730 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1731 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
1733 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1735 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1736 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1737 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1739 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1740 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1741 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1744 void PF_te_lightning2 (void)
1746 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1747 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
1749 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1751 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1752 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1753 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1755 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1756 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1757 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1760 void PF_te_lightning3 (void)
1762 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1763 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
1765 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1767 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1768 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1769 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1771 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1772 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1773 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1776 void PF_te_beam (void)
1778 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1779 MSG_WriteByte(&sv.datagram, TE_BEAM);
1781 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1783 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1784 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1785 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1787 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1788 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1789 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1792 void PF_te_plasmaburn (void)
1794 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1795 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
1796 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1797 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1798 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1801 void PF_te_flamejet (void)
1803 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1804 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1808 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1810 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1812 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1814 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1817 static void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out)
1820 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
1822 bestdist = 1000000000;
1824 for (i = 0, e = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
1826 // clip original point to each triangle of the surface and find the
1827 // triangle that is closest
1828 v[0] = surface->groupmesh->data_vertex3f + e[0] * 3;
1829 v[1] = surface->groupmesh->data_vertex3f + e[1] * 3;
1830 v[2] = surface->groupmesh->data_vertex3f + e[2] * 3;
1831 TriangleNormal(v[0], v[1], v[2], facenormal);
1832 VectorNormalize(facenormal);
1833 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
1834 VectorMA(p, offsetdist, facenormal, temp);
1835 for (j = 0, k = 2;j < 3;k = j, j++)
1837 VectorSubtract(v[k], v[j], edgenormal);
1838 CrossProduct(edgenormal, facenormal, sidenormal);
1839 VectorNormalize(sidenormal);
1840 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
1842 VectorMA(temp, offsetdist, sidenormal, temp);
1844 dist = VectorDistance2(temp, p);
1845 if (bestdist > dist)
1848 VectorCopy(temp, out);
1853 static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum)
1857 if (!ed || ed->priv.server->free)
1859 modelindex = ed->fields.server->modelindex;
1860 if (modelindex < 1 || modelindex >= MAX_MODELS)
1862 model = sv.models[modelindex];
1863 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
1865 return model->data_surfaces + surfacenum + model->firstmodelsurface;
1869 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
1870 void PF_getsurfacenumpoints(void)
1872 msurface_t *surface;
1873 // return 0 if no such surface
1874 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1876 PRVM_G_FLOAT(OFS_RETURN) = 0;
1880 // note: this (incorrectly) assumes it is a simple polygon
1881 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
1883 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
1884 void PF_getsurfacepoint(void)
1887 msurface_t *surface;
1889 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1890 ed = PRVM_G_EDICT(OFS_PARM0);
1891 if (!ed || ed->priv.server->free)
1893 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
1895 // note: this (incorrectly) assumes it is a simple polygon
1896 pointnum = PRVM_G_FLOAT(OFS_PARM2);
1897 if (pointnum < 0 || pointnum >= surface->num_vertices)
1899 // FIXME: implement rotation/scaling
1900 VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
1902 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
1903 void PF_getsurfacenormal(void)
1905 msurface_t *surface;
1907 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1908 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1910 // FIXME: implement rotation/scaling
1911 // note: this (incorrectly) assumes it is a simple polygon
1912 // note: this only returns the first triangle, so it doesn't work very
1913 // well for curved surfaces or arbitrary meshes
1914 TriangleNormal((surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + 3, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + 6, normal);
1915 VectorNormalize(normal);
1916 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
1918 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
1919 void PF_getsurfacetexture(void)
1921 msurface_t *surface;
1922 PRVM_G_INT(OFS_RETURN) = 0;
1923 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1925 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
1927 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
1928 void PF_getsurfacenearpoint(void)
1930 int surfacenum, best, modelindex;
1932 vec_t dist, bestdist;
1935 msurface_t *surface;
1937 PRVM_G_FLOAT(OFS_RETURN) = -1;
1938 ed = PRVM_G_EDICT(OFS_PARM0);
1939 point = PRVM_G_VECTOR(OFS_PARM1);
1941 if (!ed || ed->priv.server->free)
1943 modelindex = ed->fields.server->modelindex;
1944 if (modelindex < 1 || modelindex >= MAX_MODELS)
1946 model = sv.models[modelindex];
1947 if (!model->num_surfaces)
1950 // FIXME: implement rotation/scaling
1951 VectorSubtract(point, ed->fields.server->origin, p);
1953 bestdist = 1000000000;
1954 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
1956 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
1957 // first see if the nearest point on the surface's box is closer than the previous match
1958 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
1959 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
1960 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
1961 dist = VectorLength2(clipped);
1962 if (dist < bestdist)
1964 // it is, check the nearest point on the actual geometry
1965 clippointtosurface(surface, p, clipped);
1966 VectorSubtract(clipped, p, clipped);
1967 dist += VectorLength2(clipped);
1968 if (dist < bestdist)
1970 // that's closer too, store it as the best match
1976 PRVM_G_FLOAT(OFS_RETURN) = best;
1978 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
1979 void PF_getsurfaceclippedpoint(void)
1982 msurface_t *surface;
1984 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1985 ed = PRVM_G_EDICT(OFS_PARM0);
1986 if (!ed || ed->priv.server->free)
1988 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
1990 // FIXME: implement rotation/scaling
1991 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
1992 clippointtosurface(surface, p, out);
1993 // FIXME: implement rotation/scaling
1994 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
1997 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
1998 //this function originally written by KrimZon, made shorter by LordHavoc
1999 void PF_clientcommand (void)
2001 client_t *temp_client;
2004 //find client for this entity
2005 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2006 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2008 Con_Print("PF_clientcommand: entity is not a client\n");
2012 temp_client = host_client;
2013 host_client = svs.clients + i;
2014 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2015 host_client = temp_client;
2018 //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)
2019 void PF_setattachment (void)
2021 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2022 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2023 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2028 if (e == prog->edicts)
2029 PF_WARNING("setattachment: can not modify world entity\n");
2030 if (e->priv.server->free)
2031 PF_WARNING("setattachment: can not modify free entity\n");
2033 if (tagentity == NULL)
2034 tagentity = prog->edicts;
2036 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2038 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2040 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2043 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2045 modelindex = (int)tagentity->fields.server->modelindex;
2046 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2048 v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.server->skin, tagname);
2050 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);
2053 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));
2057 /////////////////////////////////////////
2058 // DP_MD3_TAGINFO extension coded by VorteX
2060 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2065 i = e->fields.server->modelindex;
2066 if (i < 1 || i >= MAX_MODELS)
2068 model = sv.models[i];
2070 return Mod_Alias_GetTagIndexForName(model, e->fields.server->skin, tagname);
2073 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2075 float scale = PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float;
2079 Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2] + ent->fields.server->view_ofs[2], ent->fields.server->v_angle[0], ent->fields.server->v_angle[1], ent->fields.server->v_angle[2], scale);
2081 Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2], -ent->fields.server->angles[0], ent->fields.server->angles[1], ent->fields.server->angles[2], scale * 0.333);
2084 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2090 && (modelindex = ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2091 && (model = sv.models[(int)ent->fields.server->modelindex])
2092 && model->animscenes)
2094 // if model has wrong frame, engine automatically switches to model first frame
2095 frame = (int)ent->fields.server->frame;
2096 if (frame < 0 || frame >= model->numframes)
2098 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2100 Matrix4x4_CreateIdentity(out);
2104 // Warnings/errors code:
2105 // 0 - normal (everything all-right)
2108 // 3 - null or non-precached model
2109 // 4 - no tags with requested index
2110 // 5 - runaway loop at attachment chain
2111 extern cvar_t cl_bob;
2112 extern cvar_t cl_bobcycle;
2113 extern cvar_t cl_bobup;
2114 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2118 int modelindex, attachloop;
2119 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2122 Matrix4x4_CreateIdentity(out); // warnings and errors return identical matrix
2124 if (ent == prog->edicts)
2126 if (ent->priv.server->free)
2129 modelindex = (int)ent->fields.server->modelindex;
2130 if (modelindex <= 0 || modelindex > MAX_MODELS)
2133 model = sv.models[modelindex];
2135 Matrix4x4_CreateIdentity(&tagmatrix);
2136 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2140 if (attachloop >= 256) // prevent runaway looping
2142 // apply transformation by child's tagindex on parent entity and then
2143 // by parent entity itself
2144 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2145 if (ret && attachloop == 0)
2147 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2148 SV_GetEntityMatrix(ent, &entitymatrix, false);
2149 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2150 // next iteration we process the parent entity
2151 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2153 tagindex = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
2154 ent = PRVM_EDICT_NUM(val->edict);
2161 // RENDER_VIEWMODEL magic
2162 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2164 Matrix4x4_Copy(&tagmatrix, out);
2165 ent = PRVM_EDICT_NUM(val->edict);
2167 SV_GetEntityMatrix(ent, &entitymatrix, true);
2168 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2171 // Cl_bob, ported from rendering code
2172 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2175 // LordHavoc: this code is *weird*, but not replacable (I think it
2176 // should be done in QC on the server, but oh well, quake is quake)
2177 // LordHavoc: figured out bobup: the time at which the sin is at 180
2178 // degrees (which allows lengthening or squishing the peak or valley)
2179 cycle = sv.time/cl_bobcycle.value;
2180 cycle -= (int)cycle;
2181 if (cycle < cl_bobup.value)
2182 cycle = sin(M_PI * cycle / cl_bobup.value);
2184 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2185 // bob is proportional to velocity in the xy plane
2186 // (don't count Z, or jumping messes it up)
2187 bob = sqrt(ent->fields.server->velocity[0]*ent->fields.server->velocity[0] + ent->fields.server->velocity[1]*ent->fields.server->velocity[1])*cl_bob.value;
2188 bob = bob*0.3 + bob*0.7*cycle;
2189 out->m[2][3] += bound(-7, bob, 4);
2196 //float(entity ent, string tagname) gettagindex;
2198 void PF_gettagindex (void)
2200 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2201 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2202 int modelindex, tag_index;
2204 if (ent == prog->edicts)
2205 PF_WARNING("gettagindex: can't affect world entity\n");
2206 if (ent->priv.server->free)
2207 PF_WARNING("gettagindex: can't affect free entity\n");
2209 modelindex = (int)ent->fields.server->modelindex;
2211 if (modelindex <= 0 || modelindex > MAX_MODELS)
2212 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2215 tag_index = SV_GetTagIndex(ent, tag_name);
2217 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2219 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2222 //vector(entity ent, float tagindex) gettaginfo;
2223 void PF_gettaginfo (void)
2225 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2226 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2227 matrix4x4_t tag_matrix;
2230 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2231 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2236 PF_WARNING("gettagindex: can't affect world entity\n");
2239 PF_WARNING("gettagindex: can't affect free entity\n");
2242 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2245 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2248 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2253 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2254 void PF_dropclient (void)
2257 client_t *oldhostclient;
2258 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2259 if (clientnum < 0 || clientnum >= svs.maxclients)
2260 PF_WARNING("dropclient: not a client\n");
2261 if (!svs.clients[clientnum].active)
2262 PF_WARNING("dropclient: that client slot is not connected\n");
2263 oldhostclient = host_client;
2264 host_client = svs.clients + clientnum;
2265 SV_DropClient(false);
2266 host_client = oldhostclient;
2269 //entity() spawnclient (DP_SV_BOTCLIENT)
2270 void PF_spawnclient (void)
2274 prog->xfunction->builtinsprofile += 2;
2276 for (i = 0;i < svs.maxclients;i++)
2278 if (!svs.clients[i].active)
2280 prog->xfunction->builtinsprofile += 100;
2281 SV_ConnectClient (i, NULL);
2282 ed = PRVM_EDICT_NUM(i + 1);
2286 VM_RETURN_EDICT(ed);
2289 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2290 void PF_clienttype (void)
2293 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2294 if (clientnum < 0 || clientnum >= svs.maxclients)
2295 PRVM_G_FLOAT(OFS_RETURN) = 3;
2296 else if (!svs.clients[clientnum].active)
2297 PRVM_G_FLOAT(OFS_RETURN) = 0;
2298 else if (svs.clients[clientnum].netconnection)
2299 PRVM_G_FLOAT(OFS_RETURN) = 1;
2301 PRVM_G_FLOAT(OFS_RETURN) = 2;
2304 prvm_builtin_t vm_sv_builtins[] = {
2306 PF_makevectors, // #1 void(entity e) makevectors
2307 PF_setorigin, // #2 void(entity e, vector o) setorigin
2308 PF_setmodel, // #3 void(entity e, string m) setmodel
2309 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2310 NULL, // #5 void(entity e, vector min, vector max) setabssize
2311 VM_break, // #6 void() break
2312 VM_random, // #7 float() random
2313 PF_sound, // #8 void(entity e, float chan, string samp) sound
2314 VM_normalize, // #9 vector(vector v) normalize
2315 VM_error, // #10 void(string e) error
2316 VM_objerror, // #11 void(string e) objerror
2317 VM_vlen, // #12 float(vector v) vlen
2318 VM_vectoyaw, // #13 float(vector v) vectoyaw
2319 VM_spawn, // #14 entity() spawn
2320 VM_remove, // #15 void(entity e) remove
2321 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2322 PF_checkclient, // #17 entity() clientlist
2323 VM_find, // #18 entity(entity start, .string fld, string match) find
2324 PF_precache_sound, // #19 void(string s) precache_sound
2325 PF_precache_model, // #20 void(string s) precache_model
2326 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2327 PF_findradius, // #22 entity(vector org, float rad) findradius
2328 VM_bprint, // #23 void(string s) bprint
2329 PF_sprint, // #24 void(entity client, string s) sprint
2330 VM_dprint, // #25 void(string s) dprint
2331 VM_ftos, // #26 void(string s) ftos
2332 VM_vtos, // #27 void(string s) vtos
2333 VM_coredump, // #28 void() coredump
2334 VM_traceon, // #29 void() traceon
2335 VM_traceoff, // #30 void() traceoff
2336 VM_eprint, // #31 void(entity e) eprint
2337 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2339 PF_droptofloor, // #34 float() droptofloor
2340 PF_lightstyle, // #35 void(float style, string value) lightstyle
2341 VM_rint, // #36 float(float v) rint
2342 VM_floor, // #37 float(float v) floor
2343 VM_ceil, // #38 float(float v) ceil
2345 PF_checkbottom, // #40 float(entity e) checkbottom
2346 PF_pointcontents, // #41 float(vector v) pointcontents
2348 VM_fabs, // #43 float(float f) fabs
2349 PF_aim, // #44 vector(entity e, float speed) aim
2350 VM_cvar, // #45 float(string s) cvar
2351 VM_localcmd, // #46 void(string s) localcmd
2352 VM_nextent, // #47 entity(entity e) nextent
2353 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2354 PF_changeyaw, // #49 void() ChangeYaw
2356 VM_vectoangles, // #51 vector(vector v) vectoangles
2357 PF_WriteByte, // #52 void(float to, float f) WriteByte
2358 PF_WriteChar, // #53 void(float to, float f) WriteChar
2359 PF_WriteShort, // #54 void(float to, float f) WriteShort
2360 PF_WriteLong, // #55 void(float to, float f) WriteLong
2361 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2362 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2363 PF_WriteString, // #58 void(float to, string s) WriteString
2364 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2365 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2366 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2367 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2368 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2369 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2370 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2372 SV_MoveToGoal, // #67 void(float step) movetogoal
2373 PF_precache_file, // #68 string(string s) precache_file
2374 PF_makestatic, // #69 void(entity e) makestatic
2375 VM_changelevel, // #70 void(string s) changelevel
2377 VM_cvar_set, // #72 void(string var, string val) cvar_set
2378 PF_centerprint, // #73 void(entity client, strings) centerprint
2379 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2380 PF_precache_model, // #75 string(string s) precache_model2
2381 PF_precache_sound, // #76 string(string s) precache_sound2
2382 PF_precache_file, // #77 string(string s) precache_file2
2383 PF_setspawnparms, // #78 void(entity e) setspawnparms
2386 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2395 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2396 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2397 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2398 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2399 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2400 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2401 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2402 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2403 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2404 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2415 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2416 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2417 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2418 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2419 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2420 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2421 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2422 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2423 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2424 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2425 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2426 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #200-299
2427 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2428 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2429 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2430 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2431 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2432 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2433 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2434 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2435 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2436 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2437 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2438 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2439 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2440 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2441 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2442 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2443 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2444 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2445 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2446 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2447 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2448 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2449 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2450 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2451 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2452 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2453 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2454 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2455 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2456 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2457 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2458 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2459 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2460 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2461 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2462 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2463 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2464 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2465 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2466 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2467 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2468 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2469 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2470 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2471 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2472 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2473 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2474 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2475 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2476 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2477 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2478 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2479 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2480 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2481 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2482 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2483 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2484 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2485 PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2488 e10, e10, e10, e10 // #460-499 (LordHavoc)
2491 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2493 void VM_SV_Cmd_Init(void)
2498 void VM_SV_Cmd_Reset(void)