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