p_mobj.c (15234B)
1 #include "i_system.h" 2 #include "z_zone.h" 3 #include "m_random.h" 4 5 #include "doomdef.h" 6 #include "p_local.h" 7 #include "sounds.h" 8 9 #include "st_stuff.h" 10 #include "hu_stuff.h" 11 12 #include "s_sound.h" 13 14 #include "doomstat.h" 15 16 17 void G_PlayerReborn (int player); 18 void P_SpawnMapThing (mapthing_t* mthing); 19 20 21 22 23 24 25 int test; 26 27 boolean 28 P_SetMobjState 29 ( mobj_t* mobj, 30 statenum_t state ) 31 { 32 state_t* st; 33 34 do 35 { 36 if (state == S_NULL) 37 { 38 mobj->state = (state_t *) S_NULL; 39 P_RemoveMobj (mobj); 40 return false; 41 } 42 43 st = &states[state]; 44 mobj->state = st; 45 mobj->tics = st->tics; 46 mobj->sprite = st->sprite; 47 mobj->frame = st->frame; 48 49 50 51 if (st->action.acp1) 52 st->action.acp1(mobj); 53 54 state = st->nextstate; 55 } while (!mobj->tics); 56 57 return true; 58 } 59 60 61 62 63 64 void P_ExplodeMissile (mobj_t* mo) 65 { 66 mo->momx = mo->momy = mo->momz = 0; 67 68 P_SetMobjState (mo, mobjinfo[mo->type].deathstate); 69 70 mo->tics -= P_Random()&3; 71 72 if (mo->tics < 1) 73 mo->tics = 1; 74 75 mo->flags &= ~MF_MISSILE; 76 77 if (mo->info->deathsound) 78 S_StartSound (mo, mo->info->deathsound); 79 } 80 81 82 83 84 85 #define STOPSPEED 0x1000 86 #define FRICTION 0xe800 87 88 void P_XYMovement (mobj_t* mo) 89 { 90 fixed_t ptryx; 91 fixed_t ptryy; 92 player_t* player; 93 fixed_t xmove; 94 fixed_t ymove; 95 96 if (!mo->momx && !mo->momy) 97 { 98 if (mo->flags & MF_SKULLFLY) 99 { 100 101 mo->flags &= ~MF_SKULLFLY; 102 mo->momx = mo->momy = mo->momz = 0; 103 104 P_SetMobjState (mo, mo->info->spawnstate); 105 } 106 return; 107 } 108 109 player = mo->player; 110 111 if (mo->momx > MAXMOVE) 112 mo->momx = MAXMOVE; 113 else if (mo->momx < -MAXMOVE) 114 mo->momx = -MAXMOVE; 115 116 if (mo->momy > MAXMOVE) 117 mo->momy = MAXMOVE; 118 else if (mo->momy < -MAXMOVE) 119 mo->momy = -MAXMOVE; 120 121 xmove = mo->momx; 122 ymove = mo->momy; 123 124 do 125 { 126 if (xmove > MAXMOVE/2 || ymove > MAXMOVE/2) 127 { 128 ptryx = mo->x + xmove/2; 129 ptryy = mo->y + ymove/2; 130 xmove >>= 1; 131 ymove >>= 1; 132 } 133 else 134 { 135 ptryx = mo->x + xmove; 136 ptryy = mo->y + ymove; 137 xmove = ymove = 0; 138 } 139 140 if (!P_TryMove (mo, ptryx, ptryy)) 141 { 142 143 if (mo->player) 144 { 145 P_SlideMove (mo); 146 } 147 else if (mo->flags & MF_MISSILE) 148 { 149 150 if (ceilingline && 151 ceilingline->backsector && 152 ceilingline->backsector->ceilingpic == skyflatnum) 153 { 154 155 156 157 P_RemoveMobj (mo); 158 return; 159 } 160 P_ExplodeMissile (mo); 161 } 162 else 163 mo->momx = mo->momy = 0; 164 } 165 } while (xmove || ymove); 166 167 168 if (player && player->cheats & CF_NOMOMENTUM) 169 { 170 171 mo->momx = mo->momy = 0; 172 return; 173 } 174 175 if (mo->flags & (MF_MISSILE | MF_SKULLFLY) ) 176 return; 177 178 if (mo->z > mo->floorz) 179 return; 180 181 if (mo->flags & MF_CORPSE) 182 { 183 184 185 if (mo->momx > FRACUNIT/4 186 || mo->momx < -FRACUNIT/4 187 || mo->momy > FRACUNIT/4 188 || mo->momy < -FRACUNIT/4) 189 { 190 if (mo->floorz != mo->subsector->sector->floorheight) 191 return; 192 } 193 } 194 195 if (mo->momx > -STOPSPEED 196 && mo->momx < STOPSPEED 197 && mo->momy > -STOPSPEED 198 && mo->momy < STOPSPEED 199 && (!player 200 || (player->cmd.forwardmove== 0 201 && player->cmd.sidemove == 0 ) ) ) 202 { 203 204 if ( player&&(unsigned)((player->mo->state - states)- S_PLAY_RUN1) < 4) 205 P_SetMobjState (player->mo, S_PLAY); 206 207 mo->momx = 0; 208 mo->momy = 0; 209 } 210 else 211 { 212 mo->momx = FixedMul (mo->momx, FRICTION); 213 mo->momy = FixedMul (mo->momy, FRICTION); 214 } 215 } 216 217 218 219 220 void P_ZMovement (mobj_t* mo) 221 { 222 fixed_t dist; 223 fixed_t delta; 224 225 226 if (mo->player && mo->z < mo->floorz) 227 { 228 mo->player->viewheight -= mo->floorz-mo->z; 229 230 mo->player->deltaviewheight 231 = (VIEWHEIGHT - mo->player->viewheight)>>3; 232 } 233 234 235 mo->z += mo->momz; 236 237 if ( mo->flags & MF_FLOAT 238 && mo->target) 239 { 240 241 if ( !(mo->flags & MF_SKULLFLY) 242 && !(mo->flags & MF_INFLOAT) ) 243 { 244 dist = P_AproxDistance (mo->x - mo->target->x, 245 mo->y - mo->target->y); 246 247 delta =(mo->target->z + (mo->height>>1)) - mo->z; 248 249 if (delta<0 && dist < -(delta*3) ) 250 mo->z -= FLOATSPEED; 251 else if (delta>0 && dist < (delta*3) ) 252 mo->z += FLOATSPEED; 253 } 254 255 } 256 257 258 if (mo->z <= mo->floorz) 259 { 260 261 262 263 264 265 if (mo->flags & MF_SKULLFLY) 266 { 267 268 mo->momz = -mo->momz; 269 } 270 271 if (mo->momz < 0) 272 { 273 if (mo->player 274 && mo->momz < -GRAVITY*8) 275 { 276 277 278 279 280 mo->player->deltaviewheight = mo->momz>>3; 281 S_StartSound (mo, sfx_oof); 282 } 283 mo->momz = 0; 284 } 285 mo->z = mo->floorz; 286 287 if ( (mo->flags & MF_MISSILE) 288 && !(mo->flags & MF_NOCLIP) ) 289 { 290 P_ExplodeMissile (mo); 291 return; 292 } 293 } 294 else if (! (mo->flags & MF_NOGRAVITY) ) 295 { 296 if (mo->momz == 0) 297 mo->momz = -GRAVITY*2; 298 else 299 mo->momz -= GRAVITY; 300 } 301 302 if (mo->z + mo->height > mo->ceilingz) 303 { 304 305 if (mo->momz > 0) 306 mo->momz = 0; 307 { 308 mo->z = mo->ceilingz - mo->height; 309 } 310 311 if (mo->flags & MF_SKULLFLY) 312 { 313 mo->momz = -mo->momz; 314 } 315 316 if ( (mo->flags & MF_MISSILE) 317 && !(mo->flags & MF_NOCLIP) ) 318 { 319 P_ExplodeMissile (mo); 320 return; 321 } 322 } 323 } 324 325 326 327 328 329 330 void 331 P_NightmareRespawn (mobj_t* mobj) 332 { 333 fixed_t x; 334 fixed_t y; 335 fixed_t z; 336 subsector_t* ss; 337 mobj_t* mo; 338 mapthing_t* mthing; 339 340 x = mobj->spawnpoint.x << FRACBITS; 341 y = mobj->spawnpoint.y << FRACBITS; 342 343 344 if (!P_CheckPosition (mobj, x, y) ) 345 return; 346 347 348 349 mo = P_SpawnMobj (mobj->x, 350 mobj->y, 351 mobj->subsector->sector->floorheight , MT_TFOG); 352 353 S_StartSound (mo, sfx_telept); 354 355 356 ss = R_PointInSubsector (x,y); 357 358 mo = P_SpawnMobj (x, y, ss->sector->floorheight , MT_TFOG); 359 360 S_StartSound (mo, sfx_telept); 361 362 363 mthing = &mobj->spawnpoint; 364 365 366 if (mobj->info->flags & MF_SPAWNCEILING) 367 z = ONCEILINGZ; 368 else 369 z = ONFLOORZ; 370 371 372 mo = P_SpawnMobj (x,y,z, mobj->type); 373 mo->spawnpoint = mobj->spawnpoint; 374 mo->angle = ANG45 * (mthing->angle/45); 375 376 if (mthing->options & MTF_AMBUSH) 377 mo->flags |= MF_AMBUSH; 378 379 mo->reactiontime = 18; 380 381 382 P_RemoveMobj (mobj); 383 } 384 385 386 387 388 389 void P_MobjThinker (mobj_t* mobj) 390 { 391 392 if (mobj->momx 393 || mobj->momy 394 || (mobj->flags&MF_SKULLFLY) ) 395 { 396 P_XYMovement (mobj); 397 398 399 if (mobj->thinker.function.acv == (actionf_v) (-1)) 400 return; 401 } 402 if ( (mobj->z != mobj->floorz) 403 || mobj->momz ) 404 { 405 P_ZMovement (mobj); 406 407 408 if (mobj->thinker.function.acv == (actionf_v) (-1)) 409 return; 410 } 411 412 413 414 415 if (mobj->tics != -1) 416 { 417 mobj->tics--; 418 419 420 if (!mobj->tics) 421 if (!P_SetMobjState (mobj, mobj->state->nextstate) ) 422 return; 423 } 424 else 425 { 426 427 if (! (mobj->flags & MF_COUNTKILL) ) 428 return; 429 430 if (!respawnmonsters) 431 return; 432 433 mobj->movecount++; 434 435 if (mobj->movecount < 12*35) 436 return; 437 438 if ( leveltime&31 ) 439 return; 440 441 if (P_Random () > 4) 442 return; 443 444 P_NightmareRespawn (mobj); 445 } 446 447 } 448 449 450 451 452 453 mobj_t* 454 P_SpawnMobj 455 ( fixed_t x, 456 fixed_t y, 457 fixed_t z, 458 mobjtype_t type ) 459 { 460 mobj_t* mobj; 461 state_t* st; 462 mobjinfo_t* info; 463 464 mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL); 465 memset (mobj, 0, sizeof (*mobj)); 466 info = &mobjinfo[type]; 467 468 mobj->type = type; 469 mobj->info = info; 470 mobj->x = x; 471 mobj->y = y; 472 mobj->radius = info->radius; 473 mobj->height = info->height; 474 mobj->flags = info->flags; 475 mobj->health = info->spawnhealth; 476 477 if (gameskill != sk_nightmare) 478 mobj->reactiontime = info->reactiontime; 479 480 mobj->lastlook = P_Random () % MAXPLAYERS; 481 482 483 st = &states[info->spawnstate]; 484 485 mobj->state = st; 486 mobj->tics = st->tics; 487 mobj->sprite = st->sprite; 488 mobj->frame = st->frame; 489 490 491 P_SetThingPosition (mobj); 492 493 mobj->floorz = mobj->subsector->sector->floorheight; 494 mobj->ceilingz = mobj->subsector->sector->ceilingheight; 495 496 if (z == ONFLOORZ) 497 mobj->z = mobj->floorz; 498 else if (z == ONCEILINGZ) 499 mobj->z = mobj->ceilingz - mobj->info->height; 500 else 501 mobj->z = z; 502 503 mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; 504 505 P_AddThinker (&mobj->thinker); 506 507 return mobj; 508 } 509 510 511 512 513 514 mapthing_t itemrespawnque[ITEMQUESIZE]; 515 int itemrespawntime[ITEMQUESIZE]; 516 int iquehead; 517 int iquetail; 518 519 520 void P_RemoveMobj (mobj_t* mobj) 521 { 522 if ((mobj->flags & MF_SPECIAL) 523 && !(mobj->flags & MF_DROPPED) 524 && (mobj->type != MT_INV) 525 && (mobj->type != MT_INS)) 526 { 527 itemrespawnque[iquehead] = mobj->spawnpoint; 528 itemrespawntime[iquehead] = leveltime; 529 iquehead = (iquehead+1)&(ITEMQUESIZE-1); 530 531 532 if (iquehead == iquetail) 533 iquetail = (iquetail+1)&(ITEMQUESIZE-1); 534 } 535 536 537 P_UnsetThingPosition (mobj); 538 539 540 S_StopSound (mobj); 541 542 543 P_RemoveThinker ((thinker_t*)mobj); 544 } 545 546 547 548 549 550 551 552 void P_RespawnSpecials (void) 553 { 554 fixed_t x; 555 fixed_t y; 556 fixed_t z; 557 558 subsector_t* ss; 559 mobj_t* mo; 560 mapthing_t* mthing; 561 562 int i; 563 564 565 if (deathmatch != 2) 566 return; 567 568 569 if (iquehead == iquetail) 570 return; 571 572 573 if (leveltime - itemrespawntime[iquetail] < 30*35) 574 return; 575 576 mthing = &itemrespawnque[iquetail]; 577 578 x = mthing->x << FRACBITS; 579 y = mthing->y << FRACBITS; 580 581 582 ss = R_PointInSubsector (x,y); 583 mo = P_SpawnMobj (x, y, ss->sector->floorheight , MT_IFOG); 584 S_StartSound (mo, sfx_itmbk); 585 586 587 for (i=0 ; i< NUMMOBJTYPES ; i++) 588 { 589 if (mthing->type == mobjinfo[i].doomednum) 590 break; 591 } 592 593 594 if (mobjinfo[i].flags & MF_SPAWNCEILING) 595 z = ONCEILINGZ; 596 else 597 z = ONFLOORZ; 598 599 mo = P_SpawnMobj (x,y,z, i); 600 mo->spawnpoint = *mthing; 601 mo->angle = ANG45 * (mthing->angle/45); 602 603 604 iquetail = (iquetail+1)&(ITEMQUESIZE-1); 605 } 606 607 608 609 610 611 612 613 614 615 616 void P_SpawnPlayer (mapthing_t* mthing) 617 { 618 player_t* p; 619 fixed_t x; 620 fixed_t y; 621 fixed_t z; 622 623 mobj_t* mobj; 624 625 int i; 626 627 628 if (!playeringame[mthing->type-1]) 629 return; 630 631 p = &players[mthing->type-1]; 632 633 if (p->playerstate == PST_REBORN) 634 G_PlayerReborn (mthing->type-1); 635 636 x = mthing->x << FRACBITS; 637 y = mthing->y << FRACBITS; 638 z = ONFLOORZ; 639 mobj = P_SpawnMobj (x,y,z, MT_PLAYER); 640 641 642 if (mthing->type > 1) 643 mobj->flags |= (mthing->type-1)<<MF_TRANSSHIFT; 644 645 mobj->angle = ANG45 * (mthing->angle/45); 646 mobj->player = p; 647 mobj->health = p->health; 648 649 p->mo = mobj; 650 p->playerstate = PST_LIVE; 651 p->refire = 0; 652 p->message = NULL; 653 p->damagecount = 0; 654 p->bonuscount = 0; 655 p->extralight = 0; 656 p->fixedcolormap = 0; 657 p->viewheight = VIEWHEIGHT; 658 659 660 P_SetupPsprites (p); 661 662 663 if (deathmatch) 664 for (i=0 ; i<NUMCARDS ; i++) 665 p->cards[i] = true; 666 667 if (mthing->type-1 == consoleplayer) 668 { 669 670 ST_Start (); 671 672 HU_Start (); 673 } 674 } 675 676 677 678 679 680 681 682 void P_SpawnMapThing (mapthing_t* mthing) 683 { 684 int i; 685 int bit; 686 mobj_t* mobj; 687 fixed_t x; 688 fixed_t y; 689 fixed_t z; 690 691 692 if (mthing->type == 11) 693 { 694 if (deathmatch_p < &deathmatchstarts[10]) 695 { 696 memcpy (deathmatch_p, mthing, sizeof(*mthing)); 697 deathmatch_p++; 698 } 699 return; 700 } 701 702 703 if (mthing->type <= 4) 704 { 705 706 playerstarts[mthing->type-1] = *mthing; 707 if (!deathmatch) 708 P_SpawnPlayer (mthing); 709 710 return; 711 } 712 713 714 if (!netgame && (mthing->options & 16) ) 715 return; 716 717 if (gameskill == sk_baby) 718 bit = 1; 719 else if (gameskill == sk_nightmare) 720 bit = 4; 721 else 722 bit = 1<<(gameskill-1); 723 724 if (!(mthing->options & bit) ) 725 return; 726 727 728 for (i=0 ; i< NUMMOBJTYPES ; i++) 729 if (mthing->type == mobjinfo[i].doomednum) 730 break; 731 732 if (i==NUMMOBJTYPES) 733 I_Error ("P_SpawnMapThing: Unknown type %i at (%i, %i)", 734 mthing->type, 735 mthing->x, mthing->y); 736 737 738 if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH) 739 return; 740 741 742 if (nomonsters 743 && ( i == MT_SKULL 744 || (mobjinfo[i].flags & MF_COUNTKILL)) ) 745 { 746 return; 747 } 748 749 750 x = mthing->x << FRACBITS; 751 y = mthing->y << FRACBITS; 752 753 if (mobjinfo[i].flags & MF_SPAWNCEILING) 754 z = ONCEILINGZ; 755 else 756 z = ONFLOORZ; 757 758 mobj = P_SpawnMobj (x,y,z, i); 759 mobj->spawnpoint = *mthing; 760 761 if (mobj->tics > 0) 762 mobj->tics = 1 + (P_Random () % mobj->tics); 763 if (mobj->flags & MF_COUNTKILL) 764 totalkills++; 765 if (mobj->flags & MF_COUNTITEM) 766 totalitems++; 767 768 mobj->angle = ANG45 * (mthing->angle/45); 769 if (mthing->options & MTF_AMBUSH) 770 mobj->flags |= MF_AMBUSH; 771 } 772 773 774 775 776 777 778 779 780 781 782 783 extern fixed_t attackrange; 784 785 void 786 P_SpawnPuff 787 ( fixed_t x, 788 fixed_t y, 789 fixed_t z ) 790 { 791 mobj_t* th; 792 793 z += ((P_Random()-P_Random())<<10); 794 795 th = P_SpawnMobj (x,y,z, MT_PUFF); 796 th->momz = FRACUNIT; 797 th->tics -= P_Random()&3; 798 799 if (th->tics < 1) 800 th->tics = 1; 801 802 803 if (attackrange == MELEERANGE) 804 P_SetMobjState (th, S_PUFF3); 805 } 806 807 808 809 810 811 812 void 813 P_SpawnBlood 814 ( fixed_t x, 815 fixed_t y, 816 fixed_t z, 817 int damage ) 818 { 819 mobj_t* th; 820 821 z += ((P_Random()-P_Random())<<10); 822 th = P_SpawnMobj (x,y,z, MT_BLOOD); 823 th->momz = FRACUNIT*2; 824 th->tics -= P_Random()&3; 825 826 if (th->tics < 1) 827 th->tics = 1; 828 829 if (damage <= 12 && damage >= 9) 830 P_SetMobjState (th,S_BLOOD2); 831 else if (damage < 9) 832 P_SetMobjState (th,S_BLOOD3); 833 } 834 835 836 837 838 839 840 841 842 void P_CheckMissileSpawn (mobj_t* th) 843 { 844 th->tics -= P_Random()&3; 845 if (th->tics < 1) 846 th->tics = 1; 847 848 849 850 th->x += (th->momx>>1); 851 th->y += (th->momy>>1); 852 th->z += (th->momz>>1); 853 854 if (!P_TryMove (th, th->x, th->y)) 855 P_ExplodeMissile (th); 856 } 857 858 859 860 861 862 mobj_t* 863 P_SpawnMissile 864 ( mobj_t* source, 865 mobj_t* dest, 866 mobjtype_t type ) 867 { 868 mobj_t* th; 869 angle_t an; 870 int dist; 871 872 th = P_SpawnMobj (source->x, 873 source->y, 874 source->z + 4*8*FRACUNIT, type); 875 876 if (th->info->seesound) 877 S_StartSound (th, th->info->seesound); 878 879 th->target = source; 880 an = R_PointToAngle2 (source->x, source->y, dest->x, dest->y); 881 882 883 if (dest->flags & MF_SHADOW) 884 an += (P_Random()-P_Random())<<20; 885 886 th->angle = an; 887 an >>= ANGLETOFINESHIFT; 888 th->momx = FixedMul (th->info->speed, finecosine[an]); 889 th->momy = FixedMul (th->info->speed, finesine[an]); 890 891 dist = P_AproxDistance (dest->x - source->x, dest->y - source->y); 892 dist = dist / th->info->speed; 893 894 if (dist < 1) 895 dist = 1; 896 897 th->momz = (dest->z - source->z) / dist; 898 P_CheckMissileSpawn (th); 899 900 return th; 901 } 902 903 904 905 906 907 908 void 909 P_SpawnPlayerMissile 910 ( mobj_t* source, 911 mobjtype_t type ) 912 { 913 mobj_t* th; 914 angle_t an; 915 916 fixed_t x; 917 fixed_t y; 918 fixed_t z; 919 fixed_t slope; 920 921 922 an = source->angle; 923 slope = P_AimLineAttack (source, an, 16*64*FRACUNIT); 924 925 if (!linetarget) 926 { 927 an += 1<<26; 928 slope = P_AimLineAttack (source, an, 16*64*FRACUNIT); 929 930 if (!linetarget) 931 { 932 an -= 2<<26; 933 slope = P_AimLineAttack (source, an, 16*64*FRACUNIT); 934 } 935 936 if (!linetarget) 937 { 938 an = source->angle; 939 slope = 0; 940 } 941 } 942 943 x = source->x; 944 y = source->y; 945 z = source->z + 4*8*FRACUNIT; 946 947 th = P_SpawnMobj (x,y,z, type); 948 949 if (th->info->seesound) 950 S_StartSound (th, th->info->seesound); 951 952 th->target = source; 953 th->angle = an; 954 th->momx = FixedMul( th->info->speed, 955 finecosine[an>>ANGLETOFINESHIFT]); 956 th->momy = FixedMul( th->info->speed, 957 finesine[an>>ANGLETOFINESHIFT]); 958 th->momz = FixedMul( th->info->speed, slope); 959 960 P_CheckMissileSpawn (th); 961 } 962