1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21 #include "quakedef.h"
22
23 #define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e))
24
25 /*
26 ===============================================================================
27
28 BUILT-IN FUNCTIONS
29
30 ===============================================================================
31 */
32
PF_VarString(int first)33 char *PF_VarString (int first)
34 {
35 int i;
36 static char out[256];
37
38 out[0] = 0;
39 for (i=first ; i<pr_argc ; i++)
40 {
41 strcat (out, G_STRING((OFS_PARM0+i*3)));
42 }
43 return out;
44 }
45
46
47 /*
48 =================
49 PF_errror
50
51 This is a TERMINAL error, which will kill off the entire server.
52 Dumps self.
53
54 error(value)
55 =================
56 */
PF_error(void)57 void PF_error (void)
58 {
59 char *s;
60 edict_t *ed;
61
62 s = PF_VarString(0);
63 Con_Printf ("======SERVER ERROR in %s:\n%s\n"
64 ,pr_strings + pr_xfunction->s_name,s);
65 ed = PROG_TO_EDICT(pr_global_struct->self);
66 ED_Print (ed);
67
68 Host_Error ("Program error");
69 }
70
71 /*
72 =================
73 PF_objerror
74
75 Dumps out self, then an error message. The program is aborted and self is
76 removed, but the level can continue.
77
78 objerror(value)
79 =================
80 */
PF_objerror(void)81 void PF_objerror (void)
82 {
83 char *s;
84 edict_t *ed;
85
86 s = PF_VarString(0);
87 Con_Printf ("======OBJECT ERROR in %s:\n%s\n"
88 ,pr_strings + pr_xfunction->s_name,s);
89 ed = PROG_TO_EDICT(pr_global_struct->self);
90 ED_Print (ed);
91 ED_Free (ed);
92
93 Host_Error ("Program error");
94 }
95
96
97
98 /*
99 ==============
100 PF_makevectors
101
102 Writes new values for v_forward, v_up, and v_right based on angles
103 makevectors(vector)
104 ==============
105 */
PF_makevectors(void)106 void PF_makevectors (void)
107 {
108 AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
109 }
110
111 /*
112 =================
113 PF_setorigin
114
115 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.
116
117 setorigin (entity, origin)
118 =================
119 */
PF_setorigin(void)120 void PF_setorigin (void)
121 {
122 edict_t *e;
123 float *org;
124
125 e = G_EDICT(OFS_PARM0);
126 org = G_VECTOR(OFS_PARM1);
127 VectorCopy (org, e->v.origin);
128 SV_LinkEdict (e, false);
129 }
130
131
SetMinMaxSize(edict_t * e,float * min,float * max,qboolean rotate)132 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
133 {
134 float *angles;
135 vec3_t rmin, rmax;
136 float bounds[2][3];
137 float xvector[2], yvector[2];
138 float a;
139 vec3_t base, transformed;
140 int i, j, k, l;
141
142 for (i=0 ; i<3 ; i++)
143 if (min[i] > max[i])
144 PR_RunError ("backwards mins/maxs");
145
146 rotate = false; // FIXME: implement rotation properly again
147
148 if (!rotate)
149 {
150 VectorCopy (min, rmin);
151 VectorCopy (max, rmax);
152 }
153 else
154 {
155 // find min / max for rotations
156 angles = e->v.angles;
157
158 a = angles[1]/180 * M_PI;
159
160 xvector[0] = cos(a);
161 xvector[1] = sin(a);
162 yvector[0] = -sin(a);
163 yvector[1] = cos(a);
164
165 VectorCopy (min, bounds[0]);
166 VectorCopy (max, bounds[1]);
167
168 rmin[0] = rmin[1] = rmin[2] = 9999;
169 rmax[0] = rmax[1] = rmax[2] = -9999;
170
171 for (i=0 ; i<= 1 ; i++)
172 {
173 base[0] = bounds[i][0];
174 for (j=0 ; j<= 1 ; j++)
175 {
176 base[1] = bounds[j][1];
177 for (k=0 ; k<= 1 ; k++)
178 {
179 base[2] = bounds[k][2];
180
181 // transform the point
182 transformed[0] = xvector[0]*base[0] + yvector[0]*base[1];
183 transformed[1] = xvector[1]*base[0] + yvector[1]*base[1];
184 transformed[2] = base[2];
185
186 for (l=0 ; l<3 ; l++)
187 {
188 if (transformed[l] < rmin[l])
189 rmin[l] = transformed[l];
190 if (transformed[l] > rmax[l])
191 rmax[l] = transformed[l];
192 }
193 }
194 }
195 }
196 }
197
198 // set derived values
199 VectorCopy (rmin, e->v.mins);
200 VectorCopy (rmax, e->v.maxs);
201 VectorSubtract (max, min, e->v.size);
202
203 SV_LinkEdict (e, false);
204 }
205
206 /*
207 =================
208 PF_setsize
209
210 the size box is rotated by the current angle
211
212 setsize (entity, minvector, maxvector)
213 =================
214 */
PF_setsize(void)215 void PF_setsize (void)
216 {
217 edict_t *e;
218 float *min, *max;
219
220 e = G_EDICT(OFS_PARM0);
221 min = G_VECTOR(OFS_PARM1);
222 max = G_VECTOR(OFS_PARM2);
223 SetMinMaxSize (e, min, max, false);
224 }
225
226
227 /*
228 =================
229 PF_setmodel
230
231 setmodel(entity, model)
232 =================
233 */
PF_setmodel(void)234 void PF_setmodel (void)
235 {
236 edict_t *e;
237 char *m, **check;
238 model_t *mod;
239 int i;
240
241 e = G_EDICT(OFS_PARM0);
242 m = G_STRING(OFS_PARM1);
243
244 // check to see if model was properly precached
245 for (i=0, check = sv.model_precache ; *check ; i++, check++)
246 if (!strcmp(*check, m))
247 break;
248
249 if (!*check)
250 PR_RunError ("no precache: %s\n", m);
251
252 //Con_Printf("Setmodel: found model %s %i\n",m,i);
253
254 e->v.model = m - pr_strings;
255 e->v.modelindex = i; //SV_ModelIndex (m);
256
257 mod = sv.models[ (int)e->v.modelindex]; // Mod_ForName (m, true);
258
259 if (mod)
260 SetMinMaxSize (e, mod->mins, mod->maxs, true);
261 else
262 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
263 }
264
265 /*
266 =================
267 PF_bprint
268
269 broadcast print to everyone on server
270
271 bprint(value)
272 =================
273 */
PF_bprint(void)274 void PF_bprint (void)
275 {
276 char *s;
277
278 s = PF_VarString(0);
279 SV_BroadcastPrintf ("%s", s);
280 }
281
282 /*
283 =================
284 PF_sprint
285
286 single print to a specific client
287
288 sprint(clientent, value)
289 =================
290 */
PF_sprint(void)291 void PF_sprint (void)
292 {
293 char *s;
294 client_t *client;
295 int entnum;
296
297 entnum = G_EDICTNUM(OFS_PARM0);
298 s = PF_VarString(1);
299
300 if (entnum < 1 || entnum > svs.maxclients)
301 {
302 Con_Printf ("tried to sprint to a non-client\n");
303 return;
304 }
305
306 client = &svs.clients[entnum-1];
307
308 MSG_WriteChar (&client->message,svc_print);
309 MSG_WriteString (&client->message, s );
310 }
311
312
313 /*
314 =================
315 PF_centerprint
316
317 single print to a specific client
318
319 centerprint(clientent, value)
320 =================
321 */
PF_centerprint(void)322 void PF_centerprint (void)
323 {
324 char *s;
325 client_t *client;
326 int entnum;
327
328 entnum = G_EDICTNUM(OFS_PARM0);
329 s = PF_VarString(1);
330
331 if (entnum < 1 || entnum > svs.maxclients)
332 {
333 Con_Printf ("tried to sprint to a non-client\n");
334 return;
335 }
336
337 client = &svs.clients[entnum-1];
338
339 MSG_WriteChar (&client->message,svc_centerprint);
340 MSG_WriteString (&client->message, s );
341 }
342
343
344 /*
345 =================
346 PF_normalize
347
348 vector normalize(vector)
349 =================
350 */
PF_normalize(void)351 void PF_normalize (void)
352 {
353 float *value1;
354 vec3_t newvalue;
355 float new;
356
357 value1 = G_VECTOR(OFS_PARM0);
358
359 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
360 new = sqrt(new);
361
362 if (new == 0)
363 newvalue[0] = newvalue[1] = newvalue[2] = 0;
364 else
365 {
366 new = 1/new;
367 newvalue[0] = value1[0] * new;
368 newvalue[1] = value1[1] * new;
369 newvalue[2] = value1[2] * new;
370 }
371
372 VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
373 }
374
375 /*
376 =================
377 PF_vlen
378
379 scalar vlen(vector)
380 =================
381 */
PF_vlen(void)382 void PF_vlen (void)
383 {
384 float *value1;
385 float new;
386
387 value1 = G_VECTOR(OFS_PARM0);
388
389 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
390 new = sqrt(new);
391
392 G_FLOAT(OFS_RETURN) = new;
393 }
394
395 /*
396 =================
397 PF_vectoyaw
398
399 float vectoyaw(vector)
400 =================
401 */
PF_vectoyaw(void)402 void PF_vectoyaw (void)
403 {
404 float *value1;
405 float yaw;
406
407 value1 = G_VECTOR(OFS_PARM0);
408
409 if (value1[1] == 0 && value1[0] == 0)
410 yaw = 0;
411 else
412 {
413 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
414 if (yaw < 0)
415 yaw += 360;
416 }
417
418 G_FLOAT(OFS_RETURN) = yaw;
419 }
420
421
422 /*
423 =================
424 PF_vectoangles
425
426 vector vectoangles(vector)
427 =================
428 */
PF_vectoangles(void)429 void PF_vectoangles (void)
430 {
431 float *value1;
432 float forward;
433 float yaw, pitch;
434
435 value1 = G_VECTOR(OFS_PARM0);
436
437 if (value1[1] == 0 && value1[0] == 0)
438 {
439 yaw = 0;
440 if (value1[2] > 0)
441 pitch = 90;
442 else
443 pitch = 270;
444 }
445 else
446 {
447 //Optimized slightly - Eradicator
448 if (value1[0])
449 {
450 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
451 if (yaw < 0)
452 yaw += 360;
453 }
454 else if (value1[1] > 0)
455 yaw = 90;
456 else
457 yaw = 270;
458
459 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
460 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
461 if (pitch < 0)
462 pitch += 360;
463 }
464
465 G_FLOAT(OFS_RETURN+0) = pitch;
466 G_FLOAT(OFS_RETURN+1) = yaw;
467 G_FLOAT(OFS_RETURN+2) = 0;
468 }
469
470 /*
471 =================
472 PF_Random
473
474 Returns a number from 0<= num < 1
475
476 random()
477 =================
478 */
PF_random(void)479 void PF_random (void)
480 {
481 float num;
482
483 num = (rand ()&0x7fff) / ((float)0x7fff);
484
485 G_FLOAT(OFS_RETURN) = num;
486 }
487
488 /*
489 =================
490 PF_particle
491
492 particle(origin, color, count)
493 =================
494 */
PF_particle(void)495 void PF_particle (void)
496 {
497 float *org, *dir;
498 float color;
499 float count;
500
501 org = G_VECTOR(OFS_PARM0);
502 dir = G_VECTOR(OFS_PARM1);
503 color = G_FLOAT(OFS_PARM2);
504 count = G_FLOAT(OFS_PARM3);
505 SV_StartParticle (org, dir, color, count);
506 }
507
508 /*
509 =================
510 PF_BasicEmitter
511
512 BasicEmitter(origin, count, effect)
513 =================
514 */
PF_BasicEmitter(void)515 void PF_BasicEmitter(void)
516 {
517 float *org;
518 float pcount;
519 char *name;
520 int size;
521
522 org = G_VECTOR(OFS_PARM0);
523 pcount = G_FLOAT(OFS_PARM1);
524 name = G_STRING(OFS_PARM2);
525
526 size = 8 + strlen(name) + 16;
527
528 //not engough space free in the packet
529 if (sv.datagram.cursize > MAX_DATAGRAM-size)
530 return;
531
532 MSG_WriteByte(&sv.datagram, svc_basicemitter);
533 MSG_WriteCoord(&sv.datagram, org[0]);
534 MSG_WriteCoord(&sv.datagram, org[1]);
535 MSG_WriteCoord(&sv.datagram, org[2]);
536 MSG_WriteByte(&sv.datagram, pcount);
537 MSG_WriteString(&sv.datagram, name);
538 }
539
540 /*
541 =================
542 PF_ExtendedEmitter
543
544 ExtendedEmitter(origin, velocity, count, tick, lifetime, effectname)
545 =================
546 */
PF_ExtendedEmitter(void)547 void PF_ExtendedEmitter(void)
548 {
549 float *org, *vel;
550 float pcount, tick, life;
551 char *name;
552 int size;
553
554 org = G_VECTOR(OFS_PARM0);
555 vel = G_VECTOR(OFS_PARM1);
556 pcount = G_FLOAT(OFS_PARM2);
557 tick = G_FLOAT(OFS_PARM3);
558 life = G_FLOAT(OFS_PARM4);
559 name = G_STRING(OFS_PARM5);
560
561 size = 22 + strlen(name) + 16;
562
563 //not engough space free in the packet
564 if (sv.datagram.cursize > MAX_DATAGRAM-size)
565 return;
566
567 MSG_WriteByte (&sv.datagram, svc_extendedemitter);
568 MSG_WriteCoord (&sv.datagram, org[0]);
569 MSG_WriteCoord (&sv.datagram, org[1]);
570 MSG_WriteCoord (&sv.datagram, org[2]);
571 MSG_WriteCoord (&sv.datagram, vel[0]);
572 MSG_WriteCoord (&sv.datagram, vel[1]);
573 MSG_WriteCoord (&sv.datagram, vel[2]);
574 MSG_WriteByte (&sv.datagram, pcount);
575 MSG_WriteLong (&sv.datagram, (life * 100));
576 MSG_WriteLong (&sv.datagram, (tick * 100));
577 MSG_WriteString (&sv.datagram, name);
578 }
579
580 /*
581 =================
582 PF_ambientsound
583
584 =================
585 */
PF_ambientsound(void)586 void PF_ambientsound (void)
587 {
588 char **check;
589 char *samp;
590 float *pos;
591 float vol, attenuation;
592 int i, soundnum;
593
594 pos = G_VECTOR (OFS_PARM0);
595 samp = G_STRING(OFS_PARM1);
596 vol = G_FLOAT(OFS_PARM2);
597 attenuation = G_FLOAT(OFS_PARM3);
598
599 // check to see if samp was properly precached
600 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
601 if (!strcmp(*check,samp))
602 break;
603
604 if (!*check)
605 {
606 Con_Printf ("no precache: %s\n", samp);
607 return;
608 }
609
610 // add an svc_spawnambient command to the level signon packet
611
612 MSG_WriteByte (&sv.signon,svc_spawnstaticsound);
613 for (i=0 ; i<3 ; i++)
614 MSG_WriteCoord(&sv.signon, pos[i]);
615
616 MSG_WriteByte (&sv.signon, soundnum);
617
618 MSG_WriteByte (&sv.signon, vol*255);
619 MSG_WriteByte (&sv.signon, attenuation*64);
620
621 }
622
623 /*
624 =================
625 PF_sound
626
627 Each entity can have eight independant sound sources, like voice,
628 weapon, feet, etc.
629
630 Channel 0 is an auto-allocate channel, the others override anything
631 allready running on that entity/channel pair.
632
633 An attenuation of 0 will play full volume everywhere in the level.
634 Larger attenuations will drop off.
635
636 =================
637 */
PF_sound(void)638 void PF_sound (void)
639 {
640 char *sample;
641 int channel;
642 edict_t *entity;
643 int volume;
644 float attenuation;
645
646 entity = G_EDICT(OFS_PARM0);
647 channel = G_FLOAT(OFS_PARM1);
648 sample = G_STRING(OFS_PARM2);
649 volume = G_FLOAT(OFS_PARM3) * 255;
650 attenuation = G_FLOAT(OFS_PARM4);
651
652 if (volume < 0 || volume > 255)
653 Sys_Error ("SV_StartSound: volume = %i", volume);
654
655 if (attenuation < 0 || attenuation > 4)
656 Sys_Error ("SV_StartSound: attenuation = %f", attenuation);
657
658 if (channel < 0 || channel > 7)
659 Sys_Error ("SV_StartSound: channel = %i", channel);
660
661 SV_StartSound (entity, channel, sample, volume, attenuation);
662 }
663
664 /*
665 =================
666 PF_break
667
668 break()
669 =================
670 */
PF_break(void)671 void PF_break (void)
672 {
673 Con_Printf ("break statement\n");
674 *(int *)-4 = 0; // dump to debugger
675 // PR_RunError ("break statement");
676 }
677
678 /*
679 =================
680 PF_traceline
681
682 Used for use tracing and shot targeting
683 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
684 if the tryents flag is set.
685
686 traceline (vector1, vector2, tryents)
687 =================
688 */
PF_traceline(void)689 void PF_traceline (void)
690 {
691 float *v1, *v2;
692 trace_t trace;
693 int nomonsters;
694 edict_t *ent;
695
696 v1 = G_VECTOR(OFS_PARM0);
697 v2 = G_VECTOR(OFS_PARM1);
698 nomonsters = G_FLOAT(OFS_PARM2);
699 ent = G_EDICT(OFS_PARM3);
700
701 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent);
702
703 pr_global_struct->trace_allsolid = trace.allsolid;
704 pr_global_struct->trace_startsolid = trace.startsolid;
705 pr_global_struct->trace_fraction = trace.fraction;
706 pr_global_struct->trace_inwater = trace.inwater;
707 pr_global_struct->trace_inopen = trace.inopen;
708 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
709 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
710 pr_global_struct->trace_plane_dist = trace.plane.dist;
711 if (trace.ent)
712 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
713 else
714 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
715 }
716
717
718 #ifdef QUAKE2
719 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
720
PF_TraceToss(void)721 void PF_TraceToss (void)
722 {
723 trace_t trace;
724 edict_t *ent;
725 edict_t *ignore;
726
727 ent = G_EDICT(OFS_PARM0);
728 ignore = G_EDICT(OFS_PARM1);
729
730 trace = SV_Trace_Toss (ent, ignore);
731
732 pr_global_struct->trace_allsolid = trace.allsolid;
733 pr_global_struct->trace_startsolid = trace.startsolid;
734 pr_global_struct->trace_fraction = trace.fraction;
735 pr_global_struct->trace_inwater = trace.inwater;
736 pr_global_struct->trace_inopen = trace.inopen;
737 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
738 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
739 pr_global_struct->trace_plane_dist = trace.plane.dist;
740 if (trace.ent)
741 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
742 else
743 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
744 }
745 #endif
746
747
748 /*
749 =================
750 PF_checkpos
751
752 Returns true if the given entity can move to the given position from it's
753 current position by walking or rolling.
754 FIXME: make work...
755 scalar checkpos (entity, vector)
756 =================
757 */
PF_checkpos(void)758 void PF_checkpos (void)
759 {
760 }
761
762 //============================================================================
763
764 byte checkpvs[MAX_MAP_LEAFS/8];
765
PF_newcheckclient(int check)766 int PF_newcheckclient (int check)
767 {
768 int i;
769 byte *pvs;
770 edict_t *ent;
771 mleaf_t *leaf;
772 vec3_t org;
773
774 // cycle to the next one
775
776 if (check < 1)
777 check = 1;
778 if (check > svs.maxclients)
779 check = svs.maxclients;
780
781 if (check == svs.maxclients)
782 i = 1;
783 else
784 i = check + 1;
785
786 for ( ; ; i++)
787 {
788 if (i == svs.maxclients+1)
789 i = 1;
790
791 ent = EDICT_NUM(i);
792
793 if (i == check)
794 break; // didn't find anything else
795
796 if (ent->free)
797 continue;
798 if (ent->v.health <= 0)
799 continue;
800 if ((int)ent->v.flags & FL_NOTARGET)
801 continue;
802
803 // anything that is a client, or has a client as an enemy
804 break;
805 }
806
807 // get the PVS for the entity
808 VectorAdd (ent->v.origin, ent->v.view_ofs, org);
809 leaf = Mod_PointInLeaf (org, sv.worldmodel);
810 pvs = Mod_LeafPVS (leaf, sv.worldmodel);
811 memcpy (checkpvs, pvs, (sv.worldmodel->numleafs+7)>>3 );
812
813 return i;
814 }
815
816 /*
817 =================
818 PF_checkclient
819
820 Returns a client (or object that has a client enemy) that would be a
821 valid target.
822
823 If there are more than one valid options, they are cycled each frame
824
825 If (self.origin + self.viewofs) is not in the PVS of the current target,
826 it is not returned at all.
827
828 name checkclient ()
829 =================
830 */
831 #define MAX_CHECK 16
832 int c_invis, c_notvis;
PF_checkclient(void)833 void PF_checkclient (void)
834 {
835 edict_t *ent, *self;
836 mleaf_t *leaf;
837 int l;
838 vec3_t view;
839
840 // find a new check if on a new frame
841 if (sv.time - sv.lastchecktime >= 0.1)
842 {
843 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
844 sv.lastchecktime = sv.time;
845 }
846
847 // return check if it might be visible
848 ent = EDICT_NUM(sv.lastcheck);
849 if (ent->free || ent->v.health <= 0)
850 {
851 RETURN_EDICT(sv.edicts);
852 return;
853 }
854
855 // if current entity can't possibly see the check entity, return 0
856 self = PROG_TO_EDICT(pr_global_struct->self);
857 VectorAdd (self->v.origin, self->v.view_ofs, view);
858 leaf = Mod_PointInLeaf (view, sv.worldmodel);
859 l = (leaf - sv.worldmodel->leafs) - 1;
860 if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) )
861 {
862 c_notvis++;
863 RETURN_EDICT(sv.edicts);
864 return;
865 }
866
867 // might be able to see it
868 c_invis++;
869 RETURN_EDICT(ent);
870 }
871
872 //============================================================================
873
874
875 /*
876 =================
877 PF_stuffcmd
878
879 Sends text over to the client's execution buffer
880
881 stuffcmd (clientent, value)
882 =================
883 */
PF_stuffcmd(void)884 void PF_stuffcmd (void)
885 {
886 int entnum;
887 char *str;
888 client_t *old;
889
890 entnum = G_EDICTNUM(OFS_PARM0);
891 if (entnum < 1 || entnum > svs.maxclients)
892 PR_RunError ("Parm 0 not a client");
893 str = G_STRING(OFS_PARM1);
894
895 old = host_client;
896 host_client = &svs.clients[entnum-1];
897 Host_ClientCommands ("%s", str);
898 host_client = old;
899 }
900
901 /*
902 =================
903 PF_localcmd
904
905 Sends text over to the client's execution buffer
906
907 localcmd (string)
908 =================
909 */
PF_localcmd(void)910 void PF_localcmd (void)
911 {
912 char *str;
913
914 str = G_STRING(OFS_PARM0);
915 Cbuf_AddText (str);
916 }
917
918 /*
919 =================
920 PF_cvar
921
922 float cvar (string)
923 =================
924 */
PF_cvar(void)925 void PF_cvar (void)
926 {
927 char *str;
928
929 str = G_STRING(OFS_PARM0);
930
931 G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str);
932 }
933
934 /*
935 =================
936 PF_cvar_set
937
938 float cvar (string)
939 =================
940 */
PF_cvar_set(void)941 void PF_cvar_set (void)
942 {
943 char *var, *val;
944
945 var = G_STRING(OFS_PARM0);
946 val = G_STRING(OFS_PARM1);
947
948 Cvar_Set (var, val);
949 }
950
951 /*
952 =================
953 PF_findradius
954
955 Returns a chain of entities that have origins within a spherical area
956
957 findradius (origin, radius)
958 =================
959 */
PF_findradius(void)960 void PF_findradius (void)
961 {
962 edict_t *ent, *chain;
963 float rad;
964 float *org;
965 vec3_t eorg;
966 int i, j;
967
968 chain = (edict_t *)sv.edicts;
969
970 org = G_VECTOR(OFS_PARM0);
971 rad = G_FLOAT(OFS_PARM1);
972
973 ent = NEXT_EDICT(sv.edicts);
974 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
975 {
976 if (ent->free)
977 continue;
978 if (ent->v.solid == SOLID_NOT)
979 continue;
980 for (j=0 ; j<3 ; j++)
981 eorg[j] = org[j] - (ent->v.origin[j] + (ent->v.mins[j] + ent->v.maxs[j])*0.5);
982 if (Length(eorg) > rad)
983 continue;
984
985 ent->v.chain = EDICT_TO_PROG(chain);
986 chain = ent;
987 }
988
989 RETURN_EDICT(chain);
990 }
991
992
993 /*
994 =========
995 PF_dprint
996 =========
997 */
PF_dprint(void)998 void PF_dprint (void)
999 {
1000 Con_DPrintf ("%s",PF_VarString(0));
1001 }
1002
1003 //fix for problem of too many ftos calls in a print - Eradicator
1004 #define STRINGTEMP_BUFFERS 16
1005 #define STRINGTEMP_LENGTH 128
1006 static char pr_string_temp[STRINGTEMP_BUFFERS][STRINGTEMP_LENGTH];
1007 static int pr_string_tempindex = 0;
1008
PR_GetTempString(void)1009 static char *PR_GetTempString(void)
1010 {
1011 char *s;
1012 s = pr_string_temp[pr_string_tempindex];
1013 pr_string_tempindex = (pr_string_tempindex + 1) % STRINGTEMP_BUFFERS;
1014 return s;
1015 }
1016
PF_ftos(void)1017 void PF_ftos (void)
1018 {
1019 float v;
1020 char *s;
1021 v = G_FLOAT(OFS_PARM0);
1022
1023 s = PR_GetTempString();
1024 sprintf (s, "%g", v);
1025 G_INT(OFS_RETURN) = s - pr_strings;
1026 }
1027
PF_fabs(void)1028 void PF_fabs (void)
1029 {
1030 float v;
1031 v = G_FLOAT(OFS_PARM0);
1032 G_FLOAT(OFS_RETURN) = fabs(v);
1033 }
1034
PF_vtos(void)1035 void PF_vtos (void)
1036 {
1037 char *s;
1038 s = PR_GetTempString();
1039 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1040 G_INT(OFS_RETURN) = s - pr_strings;
1041 }
1042
1043 #ifdef QUAKE2
PF_etos(void)1044 void PF_etos (void)
1045 {
1046 sprintf (pr_string_temp, "entity %i", G_EDICTNUM(OFS_PARM0));
1047 G_INT(OFS_RETURN) = pr_string_temp - pr_strings;
1048 }
1049 #endif
1050
PF_Spawn(void)1051 void PF_Spawn (void)
1052 {
1053 edict_t *ed;
1054 ed = ED_Alloc();
1055 RETURN_EDICT(ed);
1056 }
1057
PF_Remove(void)1058 void PF_Remove (void)
1059 {
1060 edict_t *ed;
1061
1062 ed = G_EDICT(OFS_PARM0);
1063 ED_Free (ed);
1064 }
1065
1066
1067 // entity (entity start, .string field, string match) find = #5;
PF_Find(void)1068 void PF_Find (void)
1069 #ifdef QUAKE2
1070 {
1071 int e;
1072 int f;
1073 char *s, *t;
1074 edict_t *ed;
1075 edict_t *first;
1076 edict_t *second;
1077 edict_t *last;
1078
1079 first = second = last = (edict_t *)sv.edicts;
1080 e = G_EDICTNUM(OFS_PARM0);
1081 f = G_INT(OFS_PARM1);
1082 s = G_STRING(OFS_PARM2);
1083 if (!s)
1084 PR_RunError ("PF_Find: bad search string");
1085
1086 for (e++ ; e < sv.num_edicts ; e++)
1087 {
1088 ed = EDICT_NUM(e);
1089 if (ed->free)
1090 continue;
1091 t = E_STRING(ed,f);
1092 if (!t)
1093 continue;
1094 if (!strcmp(t,s))
1095 {
1096 if (first == (edict_t *)sv.edicts)
1097 first = ed;
1098 else if (second == (edict_t *)sv.edicts)
1099 second = ed;
1100 ed->v.chain = EDICT_TO_PROG(last);
1101 last = ed;
1102 }
1103 }
1104
1105 if (first != last)
1106 {
1107 if (last != second)
1108 first->v.chain = last->v.chain;
1109 else
1110 first->v.chain = EDICT_TO_PROG(last);
1111 last->v.chain = EDICT_TO_PROG((edict_t *)sv.edicts);
1112 if (second && second != last)
1113 second->v.chain = EDICT_TO_PROG(last);
1114 }
1115 RETURN_EDICT(first);
1116 }
1117 #else
1118 {
1119 int e;
1120 int f;
1121 char *s, *t;
1122 edict_t *ed;
1123
1124 e = G_EDICTNUM(OFS_PARM0);
1125 f = G_INT(OFS_PARM1);
1126 s = G_STRING(OFS_PARM2);
1127 if (!s)
1128 PR_RunError ("PF_Find: bad search string");
1129
1130 for (e++ ; e < sv.num_edicts ; e++)
1131 {
1132 ed = EDICT_NUM(e);
1133 if (ed->free)
1134 continue;
1135 t = E_STRING(ed,f);
1136 if (!t)
1137 continue;
1138 if (!strcmp(t,s))
1139 {
1140 RETURN_EDICT(ed);
1141 return;
1142 }
1143 }
1144
1145 RETURN_EDICT(sv.edicts);
1146 }
1147 #endif
1148
PR_CheckEmptyString(char * s)1149 void PR_CheckEmptyString (char *s)
1150 {
1151 if (s[0] <= ' ')
1152 PR_RunError ("Bad string");
1153 }
1154
PF_precache_file(void)1155 void PF_precache_file (void)
1156 { // precache_file is only used to copy files with qcc, it does nothing
1157 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1158 }
1159
PF_precache_sound(void)1160 void PF_precache_sound (void)
1161 {
1162 char *s;
1163 int i;
1164
1165 if (sv.state != ss_loading)
1166 PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
1167
1168 s = G_STRING(OFS_PARM0);
1169 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1170 PR_CheckEmptyString (s);
1171
1172 for (i=0 ; i<MAX_SOUNDS ; i++)
1173 {
1174 if (!sv.sound_precache[i])
1175 {
1176 sv.sound_precache[i] = s;
1177 return;
1178 }
1179 if (!strcmp(sv.sound_precache[i], s))
1180 return;
1181 }
1182 PR_RunError ("PF_precache_sound: overflow");
1183 }
1184
PF_precache_model(void)1185 void PF_precache_model (void)
1186 {
1187 char *s;
1188 int i;
1189
1190 if (sv.state != ss_loading)
1191 PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
1192
1193 s = G_STRING(OFS_PARM0);
1194 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1195 PR_CheckEmptyString (s);
1196
1197 for (i=0 ; i<MAX_MODELS ; i++)
1198 {
1199 if (!sv.model_precache[i])
1200 {
1201 sv.model_precache[i] = s;
1202 sv.models[i] = Mod_ForName (s, true);
1203 return;
1204 }
1205 if (!strcmp(sv.model_precache[i], s))
1206 return;
1207 }
1208 PR_RunError ("PF_precache_model: overflow");
1209 }
1210
1211
PF_coredump(void)1212 void PF_coredump (void)
1213 {
1214 ED_PrintEdicts ();
1215 }
1216
PF_traceon(void)1217 void PF_traceon (void)
1218 {
1219 pr_trace = true;
1220 }
1221
PF_traceoff(void)1222 void PF_traceoff (void)
1223 {
1224 pr_trace = false;
1225 }
1226
PF_eprint(void)1227 void PF_eprint (void)
1228 {
1229 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1230 }
1231
1232 /*
1233 ===============
1234 PF_walkmove
1235
1236 float(float yaw, float dist) walkmove
1237 ===============
1238 */
PF_walkmove(void)1239 void PF_walkmove (void)
1240 {
1241 edict_t *ent;
1242 float yaw, dist;
1243 vec3_t move;
1244 dfunction_t *oldf;
1245 int oldself;
1246
1247 ent = PROG_TO_EDICT(pr_global_struct->self);
1248 yaw = G_FLOAT(OFS_PARM0);
1249 dist = G_FLOAT(OFS_PARM1);
1250
1251 if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1252 {
1253 G_FLOAT(OFS_RETURN) = 0;
1254 return;
1255 }
1256
1257 yaw = yaw*M_PI*2 / 360;
1258
1259 move[0] = cos(yaw)*dist;
1260 move[1] = sin(yaw)*dist;
1261 move[2] = 0;
1262
1263 // save program state, because SV_movestep may call other progs
1264 oldf = pr_xfunction;
1265 oldself = pr_global_struct->self;
1266
1267 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1268
1269
1270 // restore program state
1271 pr_xfunction = oldf;
1272 pr_global_struct->self = oldself;
1273 }
1274
1275 /*
1276 ===============
1277 PF_droptofloor
1278
1279 void() droptofloor
1280 ===============
1281 */
PF_droptofloor(void)1282 void PF_droptofloor (void)
1283 {
1284 edict_t *ent;
1285 vec3_t end;
1286 trace_t trace;
1287
1288 ent = PROG_TO_EDICT(pr_global_struct->self);
1289
1290 VectorCopy (ent->v.origin, end);
1291 end[2] -= 256;
1292
1293 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
1294
1295 if (trace.fraction == 1 || trace.allsolid)
1296 G_FLOAT(OFS_RETURN) = 0;
1297 else
1298 {
1299 VectorCopy (trace.endpos, ent->v.origin);
1300 SV_LinkEdict (ent, false);
1301 ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
1302 ent->v.groundentity = EDICT_TO_PROG(trace.ent);
1303 G_FLOAT(OFS_RETURN) = 1;
1304 }
1305 }
1306
1307 /*
1308 ===============
1309 PF_lightstyle
1310
1311 void(float style, string value) lightstyle
1312 ===============
1313 */
PF_lightstyle(void)1314 void PF_lightstyle (void)
1315 {
1316 int style;
1317 char *val;
1318 client_t *client;
1319 int j;
1320
1321 style = G_FLOAT(OFS_PARM0);
1322 val = G_STRING(OFS_PARM1);
1323
1324 // change the string in sv
1325 sv.lightstyles[style] = val;
1326
1327 // send message to all clients on this server
1328 if (sv.state != ss_active)
1329 return;
1330
1331 for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
1332 if (client->active || client->spawned)
1333 {
1334 MSG_WriteChar (&client->message, svc_lightstyle);
1335 MSG_WriteChar (&client->message,style);
1336 MSG_WriteString (&client->message, val);
1337 }
1338 }
1339
PF_rint(void)1340 void PF_rint (void)
1341 {
1342 float f;
1343 f = G_FLOAT(OFS_PARM0);
1344 if (f > 0)
1345 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1346 else
1347 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1348 }
PF_floor(void)1349 void PF_floor (void)
1350 {
1351 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1352 }
PF_ceil(void)1353 void PF_ceil (void)
1354 {
1355 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1356 }
1357
1358
1359 /*
1360 =============
1361 PF_checkbottom
1362 =============
1363 */
PF_checkbottom(void)1364 void PF_checkbottom (void)
1365 {
1366 edict_t *ent;
1367
1368 ent = G_EDICT(OFS_PARM0);
1369
1370 G_FLOAT(OFS_RETURN) = SV_CheckBottom (ent);
1371 }
1372
1373 /*
1374 =============
1375 PF_pointcontents
1376 =============
1377 */
PF_pointcontents(void)1378 void PF_pointcontents (void)
1379 {
1380 float *v;
1381
1382 v = G_VECTOR(OFS_PARM0);
1383
1384 G_FLOAT(OFS_RETURN) = SV_PointContents (v);
1385 }
1386
1387 /*
1388 =============
1389 PF_nextent
1390
1391 entity nextent(entity)
1392 =============
1393 */
PF_nextent(void)1394 void PF_nextent (void)
1395 {
1396 int i;
1397 edict_t *ent;
1398
1399 i = G_EDICTNUM(OFS_PARM0);
1400 while (1)
1401 {
1402 i++;
1403 if (i == sv.num_edicts)
1404 {
1405 RETURN_EDICT(sv.edicts);
1406 return;
1407 }
1408 ent = EDICT_NUM(i);
1409 if (!ent->free)
1410 {
1411 RETURN_EDICT(ent);
1412 return;
1413 }
1414 }
1415 }
1416
1417 /*
1418 =============
1419 PF_aim
1420
1421 Pick a vector for the player to shoot along
1422 vector aim(entity, missilespeed)
1423 =============
1424 */
1425 cvar_t sv_aim = {"sv_aim", "2"}; //2 is a more like FPS's today and works best with gibable corpses - Eradicator
PF_aim(void)1426 void PF_aim (void)
1427 {
1428 edict_t *ent, *check, *bestent;
1429 vec3_t start, dir, end, bestdir;
1430 int i, j;
1431 trace_t tr;
1432 float dist, bestdist;
1433 float speed;
1434
1435 ent = G_EDICT(OFS_PARM0);
1436 speed = G_FLOAT(OFS_PARM1);
1437
1438 VectorCopy (ent->v.origin, start);
1439 start[2] += 20;
1440
1441 // try sending a trace straight
1442 VectorCopy (pr_global_struct->v_forward, dir);
1443 VectorMA (start, 2048, dir, end);
1444 tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
1445 if (tr.ent && tr.ent->v.takedamage == DAMAGE_AIM
1446 && (!teamplay.value || ent->v.team <=0 || ent->v.team != tr.ent->v.team) )
1447 {
1448 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1449 return;
1450 }
1451
1452
1453 // try all possible entities
1454 VectorCopy (dir, bestdir);
1455 bestdist = sv_aim.value;
1456 bestent = NULL;
1457
1458 check = NEXT_EDICT(sv.edicts);
1459 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1460 {
1461 if (check->v.takedamage != DAMAGE_AIM)
1462 continue;
1463 if (check == ent)
1464 continue;
1465 if (teamplay.value && ent->v.team > 0 && ent->v.team == check->v.team)
1466 continue; // don't aim at teammate
1467 for (j=0 ; j<3 ; j++)
1468 end[j] = check->v.origin[j]
1469 + 0.5*(check->v.mins[j] + check->v.maxs[j]);
1470 VectorSubtract (end, start, dir);
1471 VectorNormalize (dir);
1472 dist = DotProduct (dir, pr_global_struct->v_forward);
1473 if (dist < bestdist)
1474 continue; // to far to turn
1475 tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
1476 if (tr.ent == check)
1477 { // can shoot at this one
1478 bestdist = dist;
1479 bestent = check;
1480 }
1481 }
1482
1483 if (bestent)
1484 {
1485 VectorSubtract (bestent->v.origin, ent->v.origin, dir);
1486 dist = DotProduct (dir, pr_global_struct->v_forward);
1487 VectorScale (pr_global_struct->v_forward, dist, end);
1488 end[2] = dir[2];
1489 VectorNormalize (end);
1490 VectorCopy (end, G_VECTOR(OFS_RETURN));
1491 }
1492 else
1493 {
1494 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1495 }
1496 }
1497
1498 /*
1499 ==============
1500 PF_changeyaw
1501
1502 This was a major timewaster in progs, so it was converted to C
1503 ==============
1504 */
PF_changeyaw(void)1505 void PF_changeyaw (void)
1506 {
1507 edict_t *ent;
1508 float ideal, current, move, speed;
1509
1510 ent = PROG_TO_EDICT(pr_global_struct->self);
1511 current = anglemod( ent->v.angles[1] );
1512 ideal = ent->v.ideal_yaw;
1513 speed = ent->v.yaw_speed;
1514
1515 if (current == ideal)
1516 return;
1517 move = ideal - current;
1518 if (ideal > current)
1519 {
1520 if (move >= 180)
1521 move = move - 360;
1522 }
1523 else
1524 {
1525 if (move <= -180)
1526 move = move + 360;
1527 }
1528 if (move > 0)
1529 {
1530 if (move > speed)
1531 move = speed;
1532 }
1533 else
1534 {
1535 if (move < -speed)
1536 move = -speed;
1537 }
1538
1539 ent->v.angles[1] = anglemod (current + move);
1540 }
1541
1542 #ifdef QUAKE2
1543 /*
1544 ==============
1545 PF_changepitch
1546 ==============
1547 */
PF_changepitch(void)1548 void PF_changepitch (void)
1549 {
1550 edict_t *ent;
1551 float ideal, current, move, speed;
1552
1553 ent = G_EDICT(OFS_PARM0);
1554 current = anglemod( ent->v.angles[0] );
1555 ideal = ent->v.idealpitch;
1556 speed = ent->v.pitch_speed;
1557
1558 if (current == ideal)
1559 return;
1560 move = ideal - current;
1561 if (ideal > current)
1562 {
1563 if (move >= 180)
1564 move = move - 360;
1565 }
1566 else
1567 {
1568 if (move <= -180)
1569 move = move + 360;
1570 }
1571 if (move > 0)
1572 {
1573 if (move > speed)
1574 move = speed;
1575 }
1576 else
1577 {
1578 if (move < -speed)
1579 move = -speed;
1580 }
1581
1582 ent->v.angles[0] = anglemod (current + move);
1583 }
1584 #endif
1585
1586 /*
1587 ===============================================================================
1588
1589 MESSAGE WRITING
1590
1591 ===============================================================================
1592 */
1593
1594 #define MSG_BROADCAST 0 // unreliable to all
1595 #define MSG_ONE 1 // reliable to one (msg_entity)
1596 #define MSG_ALL 2 // reliable to all
1597 #define MSG_INIT 3 // write to the init string
1598
WriteDest(void)1599 sizebuf_t *WriteDest (void)
1600 {
1601 int entnum;
1602 int dest;
1603 edict_t *ent;
1604
1605 dest = G_FLOAT(OFS_PARM0);
1606 switch (dest)
1607 {
1608 case MSG_BROADCAST:
1609 return &sv.datagram;
1610
1611 case MSG_ONE:
1612 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1613 entnum = NUM_FOR_EDICT(ent);
1614 if (entnum < 1 || entnum > svs.maxclients)
1615 PR_RunError ("WriteDest: not a client");
1616 return &svs.clients[entnum-1].message;
1617
1618 case MSG_ALL:
1619 return &sv.reliable_datagram;
1620
1621 case MSG_INIT:
1622 return &sv.signon;
1623
1624 default:
1625 PR_RunError ("WriteDest: bad destination");
1626 break;
1627 }
1628
1629 return NULL;
1630 }
1631
PF_WriteByte(void)1632 void PF_WriteByte (void)
1633 {
1634 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1635 }
1636
PF_WriteChar(void)1637 void PF_WriteChar (void)
1638 {
1639 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1640 }
1641
PF_WriteShort(void)1642 void PF_WriteShort (void)
1643 {
1644 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1645 }
1646
PF_WriteLong(void)1647 void PF_WriteLong (void)
1648 {
1649 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1650 }
1651
PF_WriteAngle(void)1652 void PF_WriteAngle (void)
1653 {
1654 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1655 }
1656
PF_WriteCoord(void)1657 void PF_WriteCoord (void)
1658 {
1659 MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1));
1660 }
1661
PF_WriteString(void)1662 void PF_WriteString (void)
1663 {
1664 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1665 }
1666
1667
PF_WriteEntity(void)1668 void PF_WriteEntity (void)
1669 {
1670 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1671 }
1672
1673 //=============================================================================
1674
1675 int SV_ModelIndex (char *name);
1676
PF_makestatic(void)1677 void PF_makestatic (void)
1678 {
1679 edict_t *ent;
1680 int i;
1681
1682 ent = G_EDICT(OFS_PARM0);
1683
1684 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1685
1686 MSG_WriteByte (&sv.signon, SV_ModelIndex(pr_strings + ent->v.model));
1687
1688 MSG_WriteByte (&sv.signon, ent->v.frame);
1689 MSG_WriteByte (&sv.signon, ent->v.colormap);
1690 MSG_WriteByte (&sv.signon, ent->v.skin);
1691
1692 //PENTA: new baseline fields
1693
1694 //PENTA:
1695 //-=-WARNING-=-WARNING-=-WARNING-=-WARNING-=-WARNING-=-WARNING-=-WARNING-=-WARNING
1696 //-=-WARNING-=-WARNING-=-WARNING-=-WARNING-=-WARNING-=-WARNING-=-WARNING-=-WARNING
1697 //-=-WARNING-=-WARNING-=-WARNING-=-WARNING-=-WARNING-=-WARNING-=-WARNING-=-WARNING
1698 // this code is duplicated elsewhere
1699 // but on the client side the same paring routine is used
1700 // if you change anyting here don't forget to change the other too
1701 // our you'll spend several hours debugging it
1702 MSG_WriteByte (&sv.signon, (int)(HACKY_GETFIELD(ent, eval_alpha, float, 0)*255));
1703 MSG_WriteByte (&sv.signon, HACKY_GETFIELD(ent, eval_style, float, 0));
1704 MSG_WriteShort (&sv.signon, HACKY_GETFIELD(ent, eval_light_lev, float, 300));
1705 MSG_WriteByte (&sv.signon, HACKY_GETFIELD(ent, eval_pflags, float, 0));
1706
1707 for (i=0 ; i<3 ; i++)
1708 {
1709 MSG_WriteCoord(&sv.signon, ent->v.origin[i]);
1710 MSG_WriteAngle(&sv.signon, ent->v.angles[i]);
1711 MSG_WriteByte(&sv.signon, (int)(HACKY_GETFIELD(ent, eval_color, vec3_t, vec3_origin)[i]*255));
1712 }
1713
1714 // throw the entity away now
1715 ED_Free (ent);
1716 }
1717
1718 //=============================================================================
1719
1720 /*
1721 ==============
1722 PF_setspawnparms
1723 ==============
1724 */
PF_setspawnparms(void)1725 void PF_setspawnparms (void)
1726 {
1727 edict_t *ent;
1728 int i;
1729 client_t *client;
1730
1731 ent = G_EDICT(OFS_PARM0);
1732 i = NUM_FOR_EDICT(ent);
1733 if (i < 1 || i > svs.maxclients)
1734 PR_RunError ("Entity is not a client");
1735
1736 // copy spawn parms out of the client_t
1737 client = svs.clients + (i-1);
1738
1739 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1740 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1741 }
1742
1743 /*
1744 ==============
1745 PF_changelevel
1746 ==============
1747 */
PF_changelevel(void)1748 void PF_changelevel (void)
1749 {
1750 #ifdef QUAKE2
1751 char *s1, *s2;
1752
1753 if (svs.changelevel_issued)
1754 return;
1755 svs.changelevel_issued = true;
1756
1757 s1 = G_STRING(OFS_PARM0);
1758 s2 = G_STRING(OFS_PARM1);
1759
1760 if ((int)pr_global_struct->serverflags & (SFL_NEW_UNIT | SFL_NEW_EPISODE))
1761 Cbuf_AddText (va("changelevel %s %s\n",s1, s2));
1762 else
1763 Cbuf_AddText (va("changelevel2 %s %s\n",s1, s2));
1764 #else
1765 char *s;
1766
1767 // make sure we don't issue two changelevels
1768 if (svs.changelevel_issued)
1769 return;
1770 svs.changelevel_issued = true;
1771
1772 s = G_STRING(OFS_PARM0);
1773 Cbuf_AddText (va("changelevel %s\n",s));
1774 #endif
1775 }
1776
1777
1778 #ifdef QUAKE2
1779
1780 #define CONTENT_WATER -3
1781 #define CONTENT_SLIME -4
1782 #define CONTENT_LAVA -5
1783
1784 #define FL_IMMUNE_WATER 131072
1785 #define FL_IMMUNE_SLIME 262144
1786 #define FL_IMMUNE_LAVA 524288
1787
1788 #define CHAN_VOICE 2
1789 #define CHAN_BODY 4
1790
1791 #define ATTN_NORM 1
1792
PF_WaterMove(void)1793 void PF_WaterMove (void)
1794 {
1795 edict_t *self;
1796 int flags;
1797 int waterlevel;
1798 int watertype;
1799 float drownlevel;
1800 float damage = 0.0;
1801
1802 self = PROG_TO_EDICT(pr_global_struct->self);
1803
1804 if (self->v.movetype == MOVETYPE_NOCLIP)
1805 {
1806 self->v.air_finished = sv.time + 12;
1807 G_FLOAT(OFS_RETURN) = damage;
1808 return;
1809 }
1810
1811 if (self->v.health < 0)
1812 {
1813 G_FLOAT(OFS_RETURN) = damage;
1814 return;
1815 }
1816
1817 if (self->v.deadflag == DEAD_NO)
1818 drownlevel = 3;
1819 else
1820 drownlevel = 1;
1821
1822 flags = (int)self->v.flags;
1823 waterlevel = (int)self->v.waterlevel;
1824 watertype = (int)self->v.watertype;
1825
1826 if (!(flags & (FL_IMMUNE_WATER + FL_GODMODE)))
1827 if (((flags & FL_SWIM) && (waterlevel < drownlevel)) || (waterlevel >= drownlevel))
1828 {
1829 if (self->v.air_finished < sv.time)
1830 if (self->v.pain_finished < sv.time)
1831 {
1832 self->v.dmg = self->v.dmg + 2;
1833 if (self->v.dmg > 15)
1834 self->v.dmg = 10;
1835 // T_Damage (self, world, world, self.dmg, 0, FALSE);
1836 damage = self->v.dmg;
1837 self->v.pain_finished = sv.time + 1.0;
1838 }
1839 }
1840 else
1841 {
1842 if (self->v.air_finished < sv.time)
1843 // sound (self, CHAN_VOICE, "player/gasp2.wav", 1, ATTN_NORM);
1844 SV_StartSound (self, CHAN_VOICE, "player/gasp2.wav", 255, ATTN_NORM);
1845 else if (self->v.air_finished < sv.time + 9)
1846 // sound (self, CHAN_VOICE, "player/gasp1.wav", 1, ATTN_NORM);
1847 SV_StartSound (self, CHAN_VOICE, "player/gasp1.wav", 255, ATTN_NORM);
1848 self->v.air_finished = sv.time + 12.0;
1849 self->v.dmg = 2;
1850 }
1851
1852 if (!waterlevel)
1853 {
1854 if (flags & FL_INWATER)
1855 {
1856 // play leave water sound
1857 // sound (self, CHAN_BODY, "misc/outwater.wav", 1, ATTN_NORM);
1858 SV_StartSound (self, CHAN_BODY, "misc/outwater.wav", 255, ATTN_NORM);
1859 self->v.flags = (float)(flags &~FL_INWATER);
1860 }
1861 self->v.air_finished = sv.time + 12.0;
1862 G_FLOAT(OFS_RETURN) = damage;
1863 return;
1864 }
1865
1866 if (watertype == CONTENT_LAVA)
1867 { // do damage
1868 if (!(flags & (FL_IMMUNE_LAVA + FL_GODMODE)))
1869 if (self->v.dmgtime < sv.time)
1870 {
1871 if (self->v.radsuit_finished < sv.time)
1872 self->v.dmgtime = sv.time + 0.2;
1873 else
1874 self->v.dmgtime = sv.time + 1.0;
1875 // T_Damage (self, world, world, 10*self.waterlevel, 0, TRUE);
1876 damage = (float)(10*waterlevel);
1877 }
1878 }
1879 else if (watertype == CONTENT_SLIME)
1880 { // do damage
1881 if (!(flags & (FL_IMMUNE_SLIME + FL_GODMODE)))
1882 if (self->v.dmgtime < sv.time && self->v.radsuit_finished < sv.time)
1883 {
1884 self->v.dmgtime = sv.time + 1.0;
1885 // T_Damage (self, world, world, 4*self.waterlevel, 0, TRUE);
1886 damage = (float)(4*waterlevel);
1887 }
1888 }
1889
1890 if ( !(flags & FL_INWATER) )
1891 {
1892
1893 // player enter water sound
1894 if (watertype == CONTENT_LAVA)
1895 // sound (self, CHAN_BODY, "player/inlava.wav", 1, ATTN_NORM);
1896 SV_StartSound (self, CHAN_BODY, "player/inlava.wav", 255, ATTN_NORM);
1897 if (watertype == CONTENT_WATER)
1898 // sound (self, CHAN_BODY, "player/inh2o.wav", 1, ATTN_NORM);
1899 SV_StartSound (self, CHAN_BODY, "player/inh2o.wav", 255, ATTN_NORM);
1900 if (watertype == CONTENT_SLIME)
1901 // sound (self, CHAN_BODY, "player/slimbrn2.wav", 1, ATTN_NORM);
1902 SV_StartSound (self, CHAN_BODY, "player/slimbrn2.wav", 255, ATTN_NORM);
1903
1904 self->v.flags = (float)(flags | FL_INWATER);
1905 self->v.dmgtime = 0;
1906 }
1907
1908 if (! (flags & FL_WATERJUMP) )
1909 {
1910 // self.velocity = self.velocity - 0.8*self.waterlevel*frametime*self.velocity;
1911 VectorMA (self->v.velocity, -0.8 * self->v.waterlevel * host_frametime, self->v.velocity, self->v.velocity);
1912 }
1913
1914 G_FLOAT(OFS_RETURN) = damage;
1915 }
1916
1917
PF_sin(void)1918 void PF_sin (void)
1919 {
1920 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1921 }
1922
PF_cos(void)1923 void PF_cos (void)
1924 {
1925 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1926 }
1927
PF_sqrt(void)1928 void PF_sqrt (void)
1929 {
1930 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
1931 }
1932 #endif
1933
PF_Fixme(void)1934 void PF_Fixme (void)
1935 {
1936 PR_RunError ("unimplemented bulitin");
1937 }
1938
1939
1940
1941 builtin_t pr_builtin[] =
1942 {
1943 PF_Fixme,
1944 PF_makevectors, // void(entity e) makevectors = #1;
1945 PF_setorigin, // void(entity e, vector o) setorigin = #2;
1946 PF_setmodel, // void(entity e, string m) setmodel = #3;
1947 PF_setsize, // void(entity e, vector min, vector max) setsize = #4;
1948 PF_Fixme, // void(entity e, vector min, vector max) setabssize = #5;
1949 PF_break, // void() break = #6;
1950 PF_random, // float() random = #7;
1951 PF_sound, // void(entity e, float chan, string samp) sound = #8;
1952 PF_normalize, // vector(vector v) normalize = #9;
1953 PF_error, // void(string e) error = #10;
1954 PF_objerror, // void(string e) objerror = #11;
1955 PF_vlen, // float(vector v) vlen = #12;
1956 PF_vectoyaw, // float(vector v) vectoyaw = #13;
1957 PF_Spawn, // entity() spawn = #14;
1958 PF_Remove, // void(entity e) remove = #15;
1959 PF_traceline, // float(vector v1, vector v2, float tryents) traceline = #16;
1960 PF_checkclient, // entity() clientlist = #17;
1961 PF_Find, // entity(entity start, .string fld, string match) find = #18;
1962 PF_precache_sound, // void(string s) precache_sound = #19;
1963 PF_precache_model, // void(string s) precache_model = #20;
1964 PF_stuffcmd, // void(entity client, string s)stuffcmd = #21;
1965 PF_findradius, // entity(vector org, float rad) findradius = #22;
1966 PF_bprint, // void(string s) bprint = #23;
1967 PF_sprint, // void(entity client, string s) sprint = #24;
1968 PF_dprint, // void(string s) dprint = #25;
1969 PF_ftos, // void(string s) ftos = #26;
1970 PF_vtos, // void(string s) vtos = #27;
1971 PF_coredump,
1972 PF_traceon,
1973 PF_traceoff,
1974 PF_eprint, // void(entity e) debug print an entire entity
1975 PF_walkmove, // float(float yaw, float dist) walkmove
1976 PF_Fixme, // float(float yaw, float dist) walkmove
1977 PF_droptofloor,
1978 PF_lightstyle,
1979 PF_rint,
1980 PF_floor,
1981 PF_ceil,
1982 PF_Fixme,
1983 PF_checkbottom,
1984 PF_pointcontents,
1985 PF_Fixme,
1986 PF_fabs,
1987 PF_aim,
1988 PF_cvar,
1989 PF_localcmd,
1990 PF_nextent,
1991 PF_particle,
1992 PF_changeyaw,
1993 PF_Fixme,
1994 PF_vectoangles,
1995
1996 PF_WriteByte,
1997 PF_WriteChar,
1998 PF_WriteShort,
1999 PF_WriteLong,
2000 PF_WriteCoord,
2001 PF_WriteAngle,
2002 PF_WriteString,
2003 PF_WriteEntity,
2004
2005 #ifdef QUAKE2
2006 PF_sin,
2007 PF_cos,
2008 PF_sqrt,
2009 PF_changepitch,
2010 PF_TraceToss,
2011 PF_etos,
2012 PF_WaterMove,
2013 #else
2014 PF_Fixme,
2015 PF_Fixme,
2016 PF_Fixme,
2017 PF_Fixme,
2018 PF_Fixme,
2019 PF_Fixme,
2020 PF_Fixme,
2021 #endif
2022
2023 SV_MoveToGoal,
2024 PF_precache_file,
2025 PF_makestatic,
2026
2027 PF_changelevel,
2028 PF_Fixme,
2029
2030 PF_cvar_set,
2031 PF_centerprint,
2032
2033 PF_ambientsound,
2034
2035 PF_precache_model,
2036 PF_precache_sound, // precache_sound2 is different only for qcc
2037 PF_precache_file,
2038
2039 PF_setspawnparms,
2040
2041 PF_BasicEmitter,
2042 PF_ExtendedEmitter,
2043
2044 };
2045
2046 builtin_t *pr_builtins = pr_builtin;
2047 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
2048
2049