1/* 2Copyright (C) 1996-1997 Id Software, Inc. 3 4This program is free software; you can redistribute it and/or 5modify it under the terms of the GNU General Public License 6as published by the Free Software Foundation; either version 2 7of the License, or (at your option) any later version. 8 9This program is distributed in the hope that it will be useful, 10but WITHOUT ANY WARRANTY; without even the implied warranty of 11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13See the GNU General Public License for more details. 14 15You should have received a copy of the GNU General Public License 16along with this program; if not, write to the Free Software 17Foundation, 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 33char *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================= 49PF_errror 50 51This is a TERMINAL error, which will kill off the entire server. 52Dumps self. 53 54error(value) 55================= 56*/ 57void 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================= 73PF_objerror 74 75Dumps out self, then an error message. The program is aborted and self is 76removed, but the level can continue. 77 78objerror(value) 79================= 80*/ 81void 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============== 100PF_makevectors 101 102Writes new values for v_forward, v_up, and v_right based on angles 103makevectors(vector) 104============== 105*/ 106void 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================= 113PF_setorigin 114 115This 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 117setorigin (entity, origin) 118================= 119*/ 120void 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 132void 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================= 208PF_setsize 209 210the size box is rotated by the current angle 211 212setsize (entity, minvector, maxvector) 213================= 214*/ 215void 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================= 229PF_setmodel 230 231setmodel(entity, model) 232================= 233*/ 234void 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================= 266PF_bprint 267 268broadcast print to everyone on server 269 270bprint(value) 271================= 272*/ 273void PF_bprint (void) 274{ 275 char *s; 276 277 s = PF_VarString(0); 278 SV_BroadcastPrintf ("%s", s); 279} 280 281/* 282================= 283PF_sprint 284 285single print to a specific client 286 287sprint(clientent, value) 288================= 289*/ 290void 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================= 314PF_centerprint 315 316single print to a specific client 317 318centerprint(clientent, value) 319================= 320*/ 321void 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================= 345PF_normalize 346 347vector normalize(vector) 348================= 349*/ 350void 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================= 376PF_vlen 377 378scalar vlen(vector) 379================= 380*/ 381void 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================= 396PF_vectoyaw 397 398float vectoyaw(vector) 399================= 400*/ 401void 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================= 423PF_vectoangles 424 425vector vectoangles(vector) 426================= 427*/ 428void 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================= 463PF_Random 464 465Returns a number from 0<= num < 1 466 467random() 468================= 469*/ 470void 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================= 481PF_particle 482 483particle(origin, color, count) 484================= 485*/ 486void 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================= 502PF_ambientsound 503 504================= 505*/ 506void 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================= 545PF_sound 546 547Each entity can have eight independant sound sources, like voice, 548weapon, feet, etc. 549 550Channel 0 is an auto-allocate channel, the others override anything 551allready running on that entity/channel pair. 552 553An attenuation of 0 will play full volume everywhere in the level. 554Larger attenuations will drop off. 555 556================= 557*/ 558void 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================= 586PF_break 587 588break() 589================= 590*/ 591void PF_break (void) 592{ 593Con_Printf ("break statement\n"); 594*(int *)-4 = 0; // dump to debugger 595// PR_RunError ("break statement"); 596} 597 598/* 599================= 600PF_traceline 601 602Used for use tracing and shot targeting 603Traces are blocked by bbox and exact bsp entityes, and also slide box entities 604if the tryents flag is set. 605 606traceline (vector1, vector2, tryents) 607================= 608*/ 609void 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 639extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore); 640 641void 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================= 670PF_checkpos 671 672Returns true if the given entity can move to the given position from it's 673current position by walking or rolling. 674FIXME: make work... 675scalar checkpos (entity, vector) 676================= 677*/ 678void PF_checkpos (void) 679{ 680} 681 682//============================================================================ 683 684byte checkpvs[MAX_MAP_LEAFS/8]; 685 686int 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================= 738PF_checkclient 739 740Returns a client (or object that has a client enemy) that would be a 741valid target. 742 743If there are more than one valid options, they are cycled each frame 744 745If (self.origin + self.viewofs) is not in the PVS of the current target, 746it is not returned at all. 747 748name checkclient () 749================= 750*/ 751#define MAX_CHECK 16 752int c_invis, c_notvis; 753void 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 { 782c_notvis++; 783 RETURN_EDICT(sv.edicts); 784 return; 785 } 786 787// might be able to see it 788c_invis++; 789 RETURN_EDICT(ent); 790} 791 792//============================================================================ 793 794 795/* 796================= 797PF_stuffcmd 798 799Sends text over to the client's execution buffer 800 801stuffcmd (clientent, value) 802================= 803*/ 804void 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================= 823PF_localcmd 824 825Sends text over to the client's execution buffer 826 827localcmd (string) 828================= 829*/ 830void PF_localcmd (void) 831{ 832 char *str; 833 834 str = G_STRING(OFS_PARM0); 835 Cbuf_AddText (str); 836} 837 838/* 839================= 840PF_cvar 841 842float cvar (string) 843================= 844*/ 845void 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================= 856PF_cvar_set 857 858float cvar (string) 859================= 860*/ 861void 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================= 873PF_findradius 874 875Returns a chain of entities that have origins within a spherical area 876 877findradius (origin, radius) 878================= 879*/ 880void 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========= 915PF_dprint 916========= 917*/ 918void PF_dprint (void) 919{ 920 Con_DPrintf ("%s",PF_VarString(0)); 921} 922 923char pr_string_temp[128]; 924 925void 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 937void PF_fabs (void) 938{ 939 float v; 940 v = G_FLOAT(OFS_PARM0); 941 G_FLOAT(OFS_RETURN) = fabs(v); 942} 943 944void 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 951void 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 958void PF_Spawn (void) 959{ 960 edict_t *ed; 961 ed = ED_Alloc(); 962 RETURN_EDICT(ed); 963} 964 965void 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; 975void 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 1056void PR_CheckEmptyString (char *s) 1057{ 1058 if (s[0] <= ' ') 1059 PR_RunError ("Bad string"); 1060} 1061 1062void 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 1067void 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 1092void 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 1119void PF_coredump (void) 1120{ 1121 ED_PrintEdicts (); 1122} 1123 1124void PF_traceon (void) 1125{ 1126 pr_trace = true; 1127} 1128 1129void PF_traceoff (void) 1130{ 1131 pr_trace = false; 1132} 1133 1134void PF_eprint (void) 1135{ 1136 ED_PrintNum (G_EDICTNUM(OFS_PARM0)); 1137} 1138 1139/* 1140=============== 1141PF_walkmove 1142 1143float(float yaw, float dist) walkmove 1144=============== 1145*/ 1146void 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=============== 1184PF_droptofloor 1185 1186void() droptofloor 1187=============== 1188*/ 1189void 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=============== 1216PF_lightstyle 1217 1218void(float style, string value) lightstyle 1219=============== 1220*/ 1221void 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 1247void 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} 1256void PF_floor (void) 1257{ 1258 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0)); 1259} 1260void PF_ceil (void) 1261{ 1262 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0)); 1263} 1264 1265 1266/* 1267============= 1268PF_checkbottom 1269============= 1270*/ 1271void 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============= 1282PF_pointcontents 1283============= 1284*/ 1285void 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============= 1296PF_nextent 1297 1298entity nextent(entity) 1299============= 1300*/ 1301void 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============= 1326PF_aim 1327 1328Pick a vector for the player to shoot along 1329vector aim(entity, missilespeed) 1330============= 1331*/ 1332cvar_t sv_aim = CVAR2("sv_aim", "0.93"); 1333void 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============== 1407PF_changeyaw 1408 1409This was a major timewaster in progs, so it was converted to C 1410============== 1411*/ 1412void 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============== 1452PF_changepitch 1453============== 1454*/ 1455void 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 1496MESSAGE 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 1506sizebuf_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 1539void PF_WriteByte (void) 1540{ 1541 MSG_WriteByte (WriteDest(), (int) G_FLOAT(OFS_PARM1)); 1542} 1543 1544void PF_WriteChar (void) 1545{ 1546 MSG_WriteChar (WriteDest(), (int) G_FLOAT(OFS_PARM1)); 1547} 1548 1549void PF_WriteShort (void) 1550{ 1551 MSG_WriteShort (WriteDest(), (int) G_FLOAT(OFS_PARM1)); 1552} 1553 1554void PF_WriteLong (void) 1555{ 1556 MSG_WriteLong (WriteDest(), (int) G_FLOAT(OFS_PARM1)); 1557} 1558 1559void PF_WriteAngle (void) 1560{ 1561 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1)); 1562} 1563 1564void PF_WriteCoord (void) 1565{ 1566 MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1)); 1567} 1568 1569void PF_WriteString (void) 1570{ 1571 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1)); 1572} 1573 1574 1575void PF_WriteEntity (void) 1576{ 1577 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1)); 1578} 1579 1580//============================================================================= 1581 1582int SV_ModelIndex (const char *name); 1583 1584void 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============== 1612PF_setspawnparms 1613============== 1614*/ 1615void 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============== 1635PF_changelevel 1636============== 1637*/ 1638void 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 1683void 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 1808void PF_sin (void) 1809{ 1810 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0)); 1811} 1812 1813void PF_cos (void) 1814{ 1815 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0)); 1816} 1817 1818void PF_sqrt (void) 1819{ 1820 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0)); 1821} 1822#endif 1823 1824void PF_Fixme (void) 1825{ 1826 PR_RunError ("unimplemented bulitin"); 1827} 1828 1829 1830 1831builtin_t pr_builtin[] = 1832{ 1833PF_Fixme, 1834PF_makevectors, // void(entity e) makevectors = #1; 1835PF_setorigin, // void(entity e, vector o) setorigin = #2; 1836PF_setmodel, // void(entity e, string m) setmodel = #3; 1837PF_setsize, // void(entity e, vector min, vector max) setsize = #4; 1838PF_Fixme, // void(entity e, vector min, vector max) setabssize = #5; 1839PF_break, // void() break = #6; 1840PF_random, // float() random = #7; 1841PF_sound, // void(entity e, float chan, string samp) sound = #8; 1842PF_normalize, // vector(vector v) normalize = #9; 1843PF_error, // void(string e) error = #10; 1844PF_objerror, // void(string e) objerror = #11; 1845PF_vlen, // float(vector v) vlen = #12; 1846PF_vectoyaw, // float(vector v) vectoyaw = #13; 1847PF_Spawn, // entity() spawn = #14; 1848PF_Remove, // void(entity e) remove = #15; 1849PF_traceline, // float(vector v1, vector v2, float tryents) traceline = #16; 1850PF_checkclient, // entity() clientlist = #17; 1851PF_Find, // entity(entity start, .string fld, string match) find = #18; 1852PF_precache_sound, // void(string s) precache_sound = #19; 1853PF_precache_model, // void(string s) precache_model = #20; 1854PF_stuffcmd, // void(entity client, string s)stuffcmd = #21; 1855PF_findradius, // entity(vector org, float rad) findradius = #22; 1856PF_bprint, // void(string s) bprint = #23; 1857PF_sprint, // void(entity client, string s) sprint = #24; 1858PF_dprint, // void(string s) dprint = #25; 1859PF_ftos, // void(string s) ftos = #26; 1860PF_vtos, // void(string s) vtos = #27; 1861PF_coredump, 1862PF_traceon, 1863PF_traceoff, 1864PF_eprint, // void(entity e) debug print an entire entity 1865PF_walkmove, // float(float yaw, float dist) walkmove 1866PF_Fixme, // float(float yaw, float dist) walkmove 1867PF_droptofloor, 1868PF_lightstyle, 1869PF_rint, 1870PF_floor, 1871PF_ceil, 1872PF_Fixme, 1873PF_checkbottom, 1874PF_pointcontents, 1875PF_Fixme, 1876PF_fabs, 1877PF_aim, 1878PF_cvar, 1879PF_localcmd, 1880PF_nextent, 1881PF_particle, 1882PF_changeyaw, 1883PF_Fixme, 1884PF_vectoangles, 1885 1886PF_WriteByte, 1887PF_WriteChar, 1888PF_WriteShort, 1889PF_WriteLong, 1890PF_WriteCoord, 1891PF_WriteAngle, 1892PF_WriteString, 1893PF_WriteEntity, 1894 1895#ifdef QUAKE2 1896PF_sin, 1897PF_cos, 1898PF_sqrt, 1899PF_changepitch, 1900PF_TraceToss, 1901PF_etos, 1902PF_WaterMove, 1903#else 1904PF_Fixme, 1905PF_Fixme, 1906PF_Fixme, 1907PF_Fixme, 1908PF_Fixme, 1909PF_Fixme, 1910PF_Fixme, 1911#endif 1912 1913SV_MoveToGoal, 1914PF_precache_file, 1915PF_makestatic, 1916 1917PF_changelevel, 1918PF_Fixme, 1919 1920PF_cvar_set, 1921PF_centerprint, 1922 1923PF_ambientsound, 1924 1925PF_precache_model, 1926PF_precache_sound, // precache_sound2 is different only for qcc 1927PF_precache_file, 1928 1929PF_setspawnparms 1930}; 1931 1932builtin_t *pr_builtins = pr_builtin; 1933int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]); 1934 1935