p_enemy.c (36741B)
1 /* P_enemy.c */ 2 3 #include "doomdef.h" 4 #include "p_local.h" 5 6 void A_Fall (mobj_t *actor); 7 8 typedef enum 9 { 10 DP_STRAIGHT, 11 DP_LEFT, 12 DP_RIGHT 13 } dirproj_e; 14 15 mobj_t* P_MissileAttack(mobj_t *actor, dirproj_e direction); 16 17 /* 18 =============================================================================== 19 20 ENEMY THINKING 21 22 enemies are allways spawned with targetplayer = -1, threshold = 0 23 Most monsters are spawned unaware of all players, but some can be made preaware 24 25 =============================================================================== 26 */ 27 28 /* 29 ================ 30 = 31 = P_CheckMeleeRange 32 = 33 ================ 34 */ 35 36 boolean P_CheckMeleeRange (mobj_t *actor) // 80010B90 37 { 38 mobj_t *pl; 39 fixed_t dist; 40 41 if (!(actor->flags&MF_SEETARGET)) 42 return false; 43 44 if (!actor->target) 45 return false; 46 47 pl = actor->target; 48 dist = P_AproxDistance (pl->x-actor->x, pl->y-actor->y); 49 if (dist >= MELEERANGE) 50 return false; 51 52 return true; 53 } 54 55 /* 56 ================ 57 = 58 = P_CheckMissileRange 59 = 60 ================ 61 */ 62 63 boolean P_CheckMissileRange (mobj_t *actor) // 80010C10 64 { 65 fixed_t dist; 66 67 if (!(actor->flags & MF_SEETARGET)) 68 return false; 69 70 if (actor->flags & MF_JUSTHIT) 71 { /* the target just hit the enemy, so fight back! */ 72 actor->flags &= ~MF_JUSTHIT; 73 return true; 74 } 75 76 if (actor->reactiontime) 77 return false; /* don't attack yet */ 78 79 dist = P_AproxDistance ( actor->x-actor->target->x, actor->y-actor->target->y) - 64*FRACUNIT; 80 if (!actor->info->meleestate) 81 dist -= 128*FRACUNIT; /* no melee attack, so fire more */ 82 83 dist >>= 16; 84 85 if (actor->type == MT_SKULL) 86 dist >>= 1; 87 88 if (dist > 200) 89 dist = 200; 90 91 if (P_Random() < dist) 92 return false; 93 94 return true; 95 } 96 97 98 /* 99 ================ 100 = 101 = P_Move 102 = 103 = Move in the current direction 104 = returns false if the move is blocked 105 ================ 106 */ 107 108 fixed_t xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000};// 8005ACC0 109 fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000};// 8005ACE0 110 111 extern line_t *blockline; // 800A5D9C 112 113 boolean P_Move (mobj_t *actor) // 80010D08 114 { 115 fixed_t tryx, tryy; 116 boolean good; 117 line_t *blkline; 118 119 if (actor->movedir == DI_NODIR) 120 return false; 121 122 if((actor->flags & MF_GRAVITY) != 0) 123 { 124 if(actor->floorz != actor->z) 125 { 126 return false; 127 } 128 } 129 130 tryx = actor->x + actor->info->speed * xspeed[actor->movedir]; 131 tryy = actor->y + actor->info->speed * yspeed[actor->movedir]; 132 133 if (!P_TryMove (actor, tryx, tryy) ) 134 { /* open any specials */ 135 if (actor->flags & MF_FLOAT && floatok) 136 { /* must adjust height */ 137 if (actor->z < tmfloorz) 138 actor->z += FLOATSPEED; 139 else 140 actor->z -= FLOATSPEED; 141 142 //actor->flags |= MF_INFLOAT; 143 return true; 144 } 145 146 blkline = blockline;//(line_t *)DSPRead (&blockline); 147 if (!blkline || !blkline->special) 148 return false; 149 150 actor->movedir = DI_NODIR; 151 good = false; 152 153 if(blockline->special & MLU_USE) 154 good = P_UseSpecialLine (blkline, actor); 155 156 return good; 157 } 158 //else 159 // actor->flags &= ~MF_INFLOAT; 160 161 //if (!(actor->flags & MF_FLOAT)) 162 // actor->z = actor->floorz; 163 164 return true; 165 } 166 167 168 /* 169 ================================== 170 = 171 = TryWalk 172 = 173 = Attempts to move actoron in its current (ob->moveangle) direction. 174 = 175 = If blocked by either a wall or an actor returns FALSE 176 = If move is either clear or blocked only by a door, returns TRUE and sets 177 = If a door is in the way, an OpenDoor call is made to start it opening. 178 = 179 ================================== 180 */ 181 182 boolean P_TryWalk (mobj_t *actor) // 80010E88 183 { 184 if (!P_Move (actor)) 185 return false; 186 187 actor->movecount = P_Random()&7; 188 return true; 189 } 190 191 192 /* 193 ================ 194 = 195 = P_NewChaseDir 196 = 197 ================ 198 */ 199 200 dirtype_t opposite[] = // 8005AD00 201 {DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, DI_EAST, DI_NORTHEAST, 202 DI_NORTH, DI_NORTHWEST, DI_NODIR}; 203 204 dirtype_t diags[] = {DI_NORTHWEST,DI_NORTHEAST,DI_SOUTHWEST,DI_SOUTHEAST}; // 8005AD24 205 206 void P_NewChaseDir (mobj_t *actor) // 80010ED0 207 { 208 fixed_t deltax,deltay; 209 dirtype_t d[3]; 210 dirtype_t tdir, olddir, turnaround; 211 212 if (!actor->target) 213 I_Error ("P_NewChaseDir: called with no target"); 214 215 olddir = actor->movedir; 216 turnaround=opposite[olddir]; 217 218 deltax = actor->target->x - actor->x; 219 deltay = actor->target->y - actor->y; 220 221 if (deltax>10*FRACUNIT) 222 d[1]= DI_EAST; 223 else if (deltax<-10*FRACUNIT) 224 d[1]= DI_WEST; 225 else 226 d[1]=DI_NODIR; 227 228 if (deltay<-10*FRACUNIT) 229 d[2]= DI_SOUTH; 230 else if (deltay>10*FRACUNIT) 231 d[2]= DI_NORTH; 232 else 233 d[2]=DI_NODIR; 234 235 /* try direct route */ 236 if (d[1] != DI_NODIR && d[2] != DI_NODIR) 237 { 238 actor->movedir = diags[((deltay<0)<<1)+(deltax>0)]; 239 if (actor->movedir != turnaround && P_TryWalk(actor)) 240 return; 241 } 242 243 /* try other directions */ 244 if (P_Random() > 200 || abs(deltay)>abs(deltax)) 245 { 246 tdir=d[1]; 247 d[1]=d[2]; 248 d[2]=tdir; 249 } 250 251 if (d[1]==turnaround) 252 d[1]=DI_NODIR; 253 254 if (d[2]==turnaround) 255 d[2]=DI_NODIR; 256 257 if (d[1]!=DI_NODIR) 258 { 259 actor->movedir = d[1]; 260 if (P_TryWalk(actor)) 261 return; /*either moved forward or attacked*/ 262 } 263 264 if (d[2]!=DI_NODIR) 265 { 266 actor->movedir =d[2]; 267 if (P_TryWalk(actor)) 268 return; 269 } 270 271 /* there is no direct path to the player, so pick another direction */ 272 273 if (olddir!=DI_NODIR) 274 { 275 actor->movedir =olddir; 276 if (P_TryWalk(actor)) 277 return; 278 } 279 280 if (P_Random()&1) /*randomly determine direction of search*/ 281 { 282 for (tdir=DI_EAST ; tdir<=DI_SOUTHEAST ; tdir++) 283 { 284 if (tdir!=turnaround) 285 { 286 actor->movedir =tdir; 287 if ( P_TryWalk(actor) ) 288 return; 289 } 290 } 291 } 292 else 293 { 294 for (tdir=DI_SOUTHEAST ; (int)tdir >= (int)DI_EAST;tdir--) 295 { 296 if (tdir!=turnaround) 297 { 298 actor->movedir =tdir; 299 if ( P_TryWalk(actor) ) 300 return; 301 } 302 } 303 } 304 305 if (turnaround != DI_NODIR) 306 { 307 actor->movedir =turnaround; 308 if ( P_TryWalk(actor) ) 309 return; 310 } 311 312 actor->movedir = DI_NODIR; /* can't move */ 313 } 314 315 316 /* 317 ================ 318 = 319 = P_LookForPlayers 320 = 321 = If allaround is false, only look 180 degrees in front 322 = returns true if a player is targeted 323 ================ 324 */ 325 326 boolean P_LookForPlayers (mobj_t *actor, boolean allaround) // 8001115C 327 { 328 angle_t an; 329 fixed_t dist, dist2; 330 mobj_t *mo; 331 mobj_t *mobj; 332 333 mo = actor->target; 334 if (!mo || mo->health <= 0 || !(actor->flags & MF_SEETARGET)) 335 { 336 if(actor->type > MT_PLAYERBOT3) /* for monsters */ 337 { 338 actor->target = players[0].mo; 339 } 340 else /* special case for player bots */ 341 { 342 dist2 = MAXINT; 343 344 for(mobj = mobjhead.next; mobj != &mobjhead; mobj = mobj->next) 345 { 346 347 if((mobj->flags & MF_COUNTKILL) == 0 || 348 mobj->type <= MT_PLAYERBOT3 || 349 mobj->health <= 0 || 350 mobj == actor) 351 { 352 continue; 353 } 354 355 /* find a killable target as close as possible */ 356 dist = P_AproxDistance(mobj->x - actor->x, mobj->y - actor->y); 357 if(!(dist < dist2)) 358 continue; 359 360 actor->target = mobj; 361 dist2 = dist; 362 } 363 } 364 365 return false; 366 } 367 368 if (!actor->subsector->sector->soundtarget) 369 { 370 if (!allaround) 371 { 372 an = R_PointToAngle2 (actor->x, actor->y, mo->x, mo->y) - actor->angle; 373 if (an > ANG90 && an < ANG270) 374 { 375 dist = P_AproxDistance (mo->x - actor->x, mo->y - actor->y); 376 /* if real close, react anyway */ 377 if (dist > MELEERANGE) 378 return false; /* behind back */ 379 } 380 } 381 } 382 383 return true; 384 } 385 386 387 /* 388 =============================================================================== 389 390 ACTION ROUTINES 391 392 =============================================================================== 393 */ 394 395 /* 396 ============== 397 = 398 = A_Look 399 = 400 = Stay in state until a player is sighted 401 = 402 ============== 403 */ 404 405 void A_Look (mobj_t *actor) // 80011340 406 { 407 mobj_t *targ; 408 int sound; 409 410 /* if current target is visible, start attacking */ 411 if (!P_LookForPlayers(actor, false)) 412 { 413 /* if the sector has a living soundtarget, make that the new target */ 414 actor->threshold = 0; /* any shot will wake up */ 415 targ = actor->subsector->sector->soundtarget; 416 if (targ == NULL || !(targ->flags & MF_SHOOTABLE) || (actor->flags & MF_AMBUSH)) 417 return; 418 actor->target = targ; 419 } 420 421 /* go into chase state */ 422 if (actor->info->seesound) 423 { 424 switch (actor->info->seesound) 425 { 426 case sfx_possit1://sfx_posit1: 427 case sfx_possit2://sfx_posit2: 428 case sfx_possit3://sfx_posit3: 429 sound = sfx_possit1+(P_Random()&1); 430 break; 431 case sfx_impsit1://sfx_bgsit1: 432 case sfx_impsit2://sfx_bgsit2: 433 sound = sfx_impsit1+(P_Random()&1); 434 break; 435 default: 436 sound = actor->info->seesound; 437 break; 438 } 439 440 if (actor->type == MT_RESURRECTOR || actor->type == MT_CYBORG) 441 S_StartSound(NULL, sound); // full volume 442 else 443 S_StartSound(actor, sound); 444 } 445 446 P_SetMobjState (actor, actor->info->seestate); 447 } 448 449 450 /* 451 ============== 452 = 453 = A_Chase 454 = 455 = Actor has a melee attack, so it tries to close as fast as possible 456 = 457 ============== 458 */ 459 460 void A_Chase (mobj_t *actor) // 8001146C 461 { 462 int delta; 463 464 if (actor->reactiontime) 465 actor->reactiontime--; 466 467 /* */ 468 /* modify target threshold */ 469 /* */ 470 if (actor->threshold) 471 actor->threshold--; 472 473 /* */ 474 /* turn towards movement direction if not there yet */ 475 /* */ 476 if (actor->movedir < 8) 477 { 478 actor->angle &= (7<<29); 479 delta = actor->angle - (actor->movedir << 29); 480 if (delta > 0) 481 actor->angle -= ANG90/2; 482 else if (delta < 0) 483 actor->angle += ANG90/2; 484 } 485 486 if (!actor->target || !(actor->target->flags&MF_SHOOTABLE)) 487 { /* look for a new target */ 488 if (P_LookForPlayers(actor,true)) 489 return; /* got a new target */ 490 P_SetMobjState (actor, actor->info->spawnstate); 491 return; 492 } 493 494 /* */ 495 /* don't attack twice in a row */ 496 /* */ 497 if (actor->flags & MF_JUSTATTACKED) 498 { 499 actor->flags &= ~MF_JUSTATTACKED; 500 P_NewChaseDir (actor); 501 return; 502 } 503 504 /* */ 505 /* check for melee attack */ 506 /* */ 507 if (actor->info->meleestate && P_CheckMeleeRange (actor)) 508 { 509 if (actor->info->attacksound) 510 S_StartSound (actor, actor->info->attacksound); 511 P_SetMobjState (actor, actor->info->meleestate); 512 return; 513 } 514 515 /* */ 516 /* check for missile attack */ 517 /* */ 518 #if ENABLE_NIGHTMARE == 1 519 if ((gameskill == sk_nightmare || !actor->movecount) && actor->info->missilestate 520 && P_CheckMissileRange (actor)) 521 { 522 P_SetMobjState (actor, actor->info->missilestate); 523 if (gameskill != sk_nightmare) 524 actor->flags |= MF_JUSTATTACKED; 525 return; 526 } 527 #else 528 if ( (/*gameskill == sk_nightmare || */!actor->movecount) && actor->info->missilestate 529 && P_CheckMissileRange (actor)) 530 { 531 P_SetMobjState (actor, actor->info->missilestate); 532 //if (gameskill != sk_nightmare) 533 actor->flags |= MF_JUSTATTACKED; 534 return; 535 } 536 #endif // ENABLE_NIGHTMARE 537 538 539 /* */ 540 /* chase towards player */ 541 /* */ 542 if (--actor->movecount<0 || !P_Move (actor)) 543 P_NewChaseDir (actor); 544 545 /* */ 546 /* make active sound */ 547 /* */ 548 if (actor->info->activesound && P_Random () < 3) 549 S_StartSound (actor, actor->info->activesound); 550 } 551 552 /*============================================================================= */ 553 554 /* 555 ============== 556 = 557 = A_FaceTarget 558 = 559 ============== 560 */ 561 562 void A_FaceTarget (mobj_t *actor) // 800116A8 563 { 564 int rnd1, rnd2; 565 if (!actor->target) 566 return; 567 568 actor->flags &= ~MF_AMBUSH; 569 actor->angle = R_PointToAngle2 (actor->x, actor->y , actor->target->x, actor->target->y); 570 571 if (actor->target->flags & MF_SHADOW) 572 { 573 rnd1 = P_Random(); 574 rnd2 = P_Random(); 575 actor->angle += (rnd2 - rnd1) << 21; 576 } 577 } 578 579 /* 580 ============== 581 = 582 = A_Scream 583 = 584 ============== 585 */ 586 587 void A_Scream (mobj_t *actor) // 80011740 588 { 589 int sound; 590 591 switch (actor->info->deathsound) 592 { 593 case 0: 594 return; 595 596 case sfx_posdie1://sfx_podth1: 597 case sfx_posdie2://sfx_podth2: 598 case sfx_posdie3://sfx_podth3: 599 sound = sfx_posdie1 + (P_Random ()&1); 600 break; 601 602 case sfx_impdth1://sfx_bgdth1: 603 case sfx_impdth2://sfx_bgdth2: 604 sound = sfx_impdth1 + (P_Random ()&1); 605 break; 606 607 default: 608 sound = actor->info->deathsound; 609 break; 610 } 611 612 S_StartSound(actor, sound); 613 } 614 615 /* 616 ============== 617 = 618 = A_XScream 619 = 620 ============== 621 */ 622 623 void A_XScream (mobj_t *actor) // 800117E4 624 { 625 S_StartSound (actor, sfx_slop); 626 } 627 628 /* 629 ============== 630 = 631 = A_Pain 632 = 633 ============== 634 */ 635 636 void A_Pain (mobj_t *actor) // 80011804 637 { 638 if(actor->info->painsound) 639 { 640 if(actor->type == MT_RESURRECTOR) 641 S_StartSound(NULL, actor->info->painsound); 642 else 643 S_StartSound(actor, actor->info->painsound); 644 } 645 } 646 647 /* 648 ============== 649 = 650 = A_Fall 651 = 652 ============== 653 */ 654 655 void A_Fall (mobj_t *actor) // 8001185C 656 { 657 /* actor is on ground, it can be walked over */ 658 actor->flags &= ~MF_SOLID; 659 } 660 661 662 /* 663 ================ 664 = 665 = A_Explode 666 = 667 ================ 668 */ 669 670 void A_Explode (mobj_t *thingy) // 80011870 671 { 672 P_RadiusAttack(thingy, thingy->target, 128); 673 } 674 675 676 /* 677 ================ 678 = 679 = A_OnDeathTrigger(A_BossDeath) 680 = 681 = Possibly trigger special effects 682 ================ 683 */ 684 685 void A_OnDeathTrigger (mobj_t *mo) // 80011894 686 { 687 mobj_t *mo2; 688 689 if(!(mo->flags & MF_TRIGDEATH)) 690 return; 691 692 for(mo2 = mobjhead.next; mo2 != &mobjhead; mo2 = mo2->next) 693 { 694 if((mo2->tid == mo->tid) && (mo2->health > 0)) 695 return; 696 } 697 698 if(!P_ActivateLineByTag(mo->tid, mo)) 699 { 700 macroqueue[macroidx1].activator = mo; 701 macroqueue[macroidx1].tag = mo->tid; 702 macroidx1 = (macroidx1 + 1) & 3; 703 } 704 } 705 706 /* 707 ============== 708 = 709 = A_PosAttack 710 = 711 ============== 712 */ 713 714 void A_PosAttack (mobj_t *actor) // 80011954 715 { 716 int angle, damage, rnd1, rnd2; 717 718 if (!actor->target) 719 return; 720 721 A_FaceTarget (actor); 722 angle = actor->angle; 723 724 S_StartSound (actor, sfx_pistol); 725 726 rnd1 = P_Random(); 727 rnd2 = P_Random(); 728 angle += (rnd2-rnd1)<<20; 729 730 damage = ((P_Random() & 7) * 3) + 3; 731 P_LineAttack (actor, angle, 0, MISSILERANGE, MAXINT, damage); 732 } 733 734 /* 735 ============== 736 = 737 = A_SPosAttack 738 = 739 ============== 740 */ 741 742 void A_SPosAttack (mobj_t *actor) // 800119FC 743 { 744 int i; 745 int angle, bangle, damage; 746 747 if (!actor->target) 748 return; 749 750 S_StartSound (actor, sfx_shotgun); 751 A_FaceTarget (actor); 752 bangle = actor->angle; 753 754 for (i=0 ; i<3 ; i++) 755 { 756 angle = bangle + ((P_Random()-P_Random())<<20); 757 damage = ((P_Random() % 5) * 3) + 3; 758 P_LineAttack (actor, angle, 0, MISSILERANGE, MAXINT, damage); 759 } 760 } 761 762 /* 763 ============== 764 = 765 = A_PlayAttack(A_CPosAttack) 766 = 767 ============== 768 */ 769 770 void A_PlayAttack(mobj_t* actor) // 80011b1C 771 { 772 int angle; 773 int bangle; 774 int damage; 775 int slope; 776 777 if (!actor->target) 778 return; 779 780 S_StartSound(actor, sfx_pistol); 781 A_FaceTarget(actor); 782 bangle = actor->angle; 783 784 slope = P_AimLineAttack(actor, bangle, 0, MISSILERANGE); 785 786 angle = bangle + ((P_Random() - P_Random()) << 20); 787 damage = ((P_Random() % 5) * 3) + 3; 788 P_LineAttack(actor, angle, 0, MISSILERANGE, slope, damage); 789 } 790 791 /* 792 ============== 793 = 794 = A_CPosRefire 795 = 796 ============== 797 */ 798 799 void A_CPosRefire(mobj_t* actor) // 80011BD4 800 { 801 A_FaceTarget(actor); 802 803 if (P_Random() < 40) 804 return; 805 806 if (!actor->target || actor->target->health <= 0 807 || !P_CheckSight(actor, actor->target)) 808 { 809 P_SetMobjState(actor, actor->info->seestate); 810 } 811 } 812 813 /* 814 ============== 815 = 816 = A_BspiFaceTarget 817 = 818 ============== 819 */ 820 821 void A_BspiFaceTarget(mobj_t *actor) // 80011C50 822 { 823 A_FaceTarget(actor); 824 actor->extradata = (int *)5; 825 } 826 827 /* 828 ============== 829 = 830 = A_BspiAttack 831 = 832 ============== 833 */ 834 835 void A_BspiAttack(mobj_t *actor) // 80011C74 836 { 837 if (!actor->target) 838 return; 839 840 A_FaceTarget(actor); 841 842 /* */ 843 /* launch a missile */ 844 /* */ 845 P_MissileAttack(actor, DP_LEFT); 846 P_MissileAttack(actor, DP_RIGHT); 847 } 848 849 /* 850 ============== 851 = 852 = A_SpidRefire 853 = 854 ============== 855 */ 856 857 void A_SpidRefire (mobj_t *actor) // 80011CBC 858 { 859 A_FaceTarget (actor); 860 861 if (P_Random () < 10) 862 return; 863 864 if (!actor->target || actor->target->health <= 0 || !(actor->flags&MF_SEETARGET) ) 865 { 866 P_SetMobjState (actor, actor->info->seestate); 867 actor->extradata = (int *)5; 868 return; 869 } 870 871 if(--actor->extradata <= 0) 872 { 873 P_SetMobjState(actor, actor->info->missilestate); 874 actor->extradata = (int *)5; 875 } 876 } 877 878 /* 879 ============== 880 = 881 = A_TroopMelee 882 = 883 ============== 884 */ 885 886 void A_TroopMelee(mobj_t* actor) // 80011D78 887 { 888 int damage; 889 890 if(!actor->target) 891 return; 892 893 A_FaceTarget (actor); 894 if(P_CheckMeleeRange(actor)) 895 { 896 S_StartSound(actor, sfx_scratch); 897 damage = ((P_Random() & 7) * 3) + 3; 898 P_DamageMobj(actor->target, actor, actor, damage); 899 } 900 } 901 902 /* 903 ============== 904 = 905 = A_TroopAttack 906 = 907 ============== 908 */ 909 910 void A_TroopAttack (mobj_t *actor) // 80011DEC 911 { 912 int damage; 913 914 if (!actor->target) 915 return; 916 917 A_FaceTarget (actor); 918 919 /* */ 920 /* launch a missile */ 921 /* */ 922 P_MissileAttack(actor, DP_STRAIGHT); 923 } 924 925 /* 926 ============== 927 = 928 = A_SargAttack 929 = 930 ============== 931 */ 932 933 void A_SargAttack (mobj_t *actor) // 80011E28 934 { 935 int damage; 936 937 if (!actor->target) 938 return; 939 940 A_FaceTarget (actor); 941 if(P_CheckMeleeRange(actor)) 942 { 943 damage = ((P_Random() & 7) * 4) + 4; 944 P_DamageMobj(actor->target, actor, actor, damage); 945 } 946 } 947 948 /* 949 ============== 950 = 951 = A_HeadAttack 952 = 953 ============== 954 */ 955 956 void A_HeadAttack (mobj_t *actor) // 80011E90 957 { 958 int damage; 959 960 if (!actor->target) 961 return; 962 963 A_FaceTarget (actor); 964 if (P_CheckMeleeRange (actor)) 965 { 966 damage = ((P_Random() & 7) * 8) + 8; 967 P_DamageMobj (actor->target, actor, actor, damage); 968 return; 969 } 970 /* */ 971 /* launch a missile */ 972 /* */ 973 P_MissileAttack(actor, DP_STRAIGHT); 974 } 975 976 /* 977 ============== 978 = 979 = A_CyberAttack 980 = 981 ============== 982 */ 983 984 void A_CyberAttack (mobj_t *actor) // 80011F08 985 { 986 if (!actor->target) 987 return; 988 989 A_FaceTarget (actor); 990 P_MissileAttack(actor, DP_LEFT); 991 } 992 993 /* 994 ============== 995 = 996 = A_CyberDeathEvent 997 = 998 ============== 999 */ 1000 1001 void A_CyberDeathEvent(mobj_t* actor) // 80011F44 1002 { 1003 mobjexp_t *exp; 1004 1005 //P_BossExplode(actor, 4, 12); 1006 exp = Z_Malloc (sizeof(*exp), PU_LEVSPEC, 0); 1007 P_AddThinker (&exp->thinker); 1008 exp->thinker.function = T_MobjExplode; 1009 exp->mobj = actor; 1010 exp->delay = 0; 1011 exp->delaydefault = 4; 1012 exp->lifetime = 12; 1013 S_StartSound(NULL, actor->info->deathsound); 1014 } 1015 1016 /* 1017 ============== 1018 = 1019 = A_BruisAttack 1020 = 1021 ============== 1022 */ 1023 1024 void A_BruisAttack (mobj_t *actor) // 80011FC4 1025 { 1026 int damage; 1027 1028 if (!actor->target) 1029 return; 1030 1031 if (P_CheckMeleeRange (actor)) 1032 { 1033 S_StartSound (actor, sfx_scratch); 1034 damage = ((P_Random() & 7) * 11) + 11; 1035 P_DamageMobj (actor->target, actor, actor, damage); 1036 return; 1037 } 1038 /* */ 1039 /* launch a missile */ 1040 /* */ 1041 P_MissileAttack(actor, DP_STRAIGHT); 1042 } 1043 1044 /* 1045 ============== 1046 = 1047 = A_SpawnSmoke 1048 = 1049 ============== 1050 */ 1051 1052 void A_SpawnSmoke(mobj_t *actor) // 8001204C 1053 { 1054 mobj_t *smoke; 1055 1056 smoke = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMOKE_GRAY); 1057 smoke->momz = FRACUNIT/2; 1058 } 1059 1060 /* 1061 ============== 1062 = 1063 = A_Tracer 1064 = 1065 ============== 1066 */ 1067 1068 #define TRACEANGLE 0x10000000 1069 1070 void A_Tracer(mobj_t *actor) // 80012088 1071 { 1072 angle_t exact; 1073 fixed_t dist; 1074 fixed_t slope; 1075 mobj_t *dest; 1076 mobj_t *th; 1077 1078 th = P_SpawnMobj(actor->x - actor->momx, actor->y - actor->momy, actor->z, MT_SMOKE_RED); 1079 1080 th->momz = FRACUNIT; 1081 th->tics -= P_Random() & 3; 1082 1083 if (th->tics < 1) 1084 th->tics = 1; 1085 1086 if(actor->threshold-- < -100) 1087 return; 1088 1089 // adjust direction 1090 dest = actor->tracer; 1091 1092 if (!dest || dest->health <= 0) 1093 return; 1094 1095 // change angle 1096 exact = R_PointToAngle2(actor->x, actor->y, dest->x, dest->y); 1097 1098 if (exact != actor->angle) 1099 { 1100 if (exact - actor->angle > 0x80000000) 1101 { 1102 actor->angle -= TRACEANGLE; 1103 if (exact - actor->angle < 0x80000000) 1104 actor->angle = exact; 1105 } 1106 else 1107 { 1108 actor->angle += TRACEANGLE; 1109 if (exact - actor->angle > 0x80000000) 1110 actor->angle = exact; 1111 } 1112 } 1113 1114 exact = actor->angle >> ANGLETOFINESHIFT; 1115 actor->momx = (actor->info->speed * finecosine[exact]); 1116 actor->momy = (actor->info->speed * finesine[exact]); 1117 1118 // change slope 1119 dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y); 1120 dist = dist / (actor->info->speed << FRACBITS); 1121 1122 if (dist < 1) 1123 dist = 1; 1124 1125 slope = (dest->height * 3); 1126 if(slope < 0) { 1127 slope = slope + 3; 1128 } 1129 1130 slope = (dest->z + (slope >> 2) - actor->z) / dist; 1131 1132 if (slope < actor->momz) 1133 actor->momz -= FRACUNIT / 8; 1134 else 1135 actor->momz += FRACUNIT / 4; 1136 } 1137 1138 /* 1139 ============== 1140 = 1141 = A_FatRaise 1142 = 1143 ============== 1144 */ 1145 1146 #define FATSPREAD (ANG90/4) 1147 1148 void A_FatRaise(mobj_t *actor) // 800122F4 1149 { 1150 A_FaceTarget(actor); 1151 S_StartSound(actor, sfx_fattatk); 1152 } 1153 1154 /* 1155 ============== 1156 = 1157 = A_FatAttack1 1158 = 1159 ============== 1160 */ 1161 1162 void A_FatAttack1(mobj_t *actor) // 80012320 1163 { 1164 mobj_t *mo; 1165 int an; 1166 1167 A_FaceTarget(actor); 1168 1169 // Change direction to ... 1170 P_MissileAttack(actor, DP_RIGHT); 1171 mo = P_MissileAttack(actor, DP_LEFT); 1172 1173 mo->angle += FATSPREAD; 1174 an = mo->angle >> ANGLETOFINESHIFT; 1175 mo->momx = (mo->info->speed * finecosine[an]); 1176 mo->momy = (mo->info->speed * finesine[an]); 1177 } 1178 1179 /* 1180 ============== 1181 = 1182 = A_FatAttack2 1183 = 1184 ============== 1185 */ 1186 1187 void A_FatAttack2(mobj_t *actor) // 800123B0 1188 { 1189 mobj_t *mo; 1190 mobj_t *target; 1191 int an; 1192 1193 A_FaceTarget(actor); 1194 1195 // Now here choose opposite deviation. 1196 P_MissileAttack(actor, DP_LEFT); 1197 mo = P_MissileAttack(actor, DP_RIGHT); 1198 1199 mo->angle -= FATSPREAD; 1200 an = mo->angle >> ANGLETOFINESHIFT; 1201 mo->momx = (mo->info->speed * finecosine[an]); 1202 mo->momy = (mo->info->speed * finesine[an]); 1203 } 1204 1205 /* 1206 ============== 1207 = 1208 = A_FatAttack3 1209 = 1210 ============== 1211 */ 1212 1213 void A_FatAttack3(mobj_t *actor) // 80012440 1214 { 1215 mobj_t *mo; 1216 mobj_t *target; 1217 int an; 1218 1219 A_FaceTarget(actor); 1220 1221 mo = P_MissileAttack(actor, DP_RIGHT); 1222 mo->angle -= FATSPREAD / 4; 1223 an = mo->angle >> ANGLETOFINESHIFT; 1224 mo->momx = (mo->info->speed * finecosine[an]); 1225 mo->momy = (mo->info->speed * finesine[an]); 1226 1227 mo = P_MissileAttack(actor, DP_LEFT); 1228 mo->angle += FATSPREAD / 4; 1229 an = mo->angle >> ANGLETOFINESHIFT; 1230 mo->momx = (mo->info->speed * finecosine[an]); 1231 mo->momy = (mo->info->speed * finesine[an]); 1232 } 1233 1234 1235 /* 1236 ================== 1237 = 1238 = SkullAttack 1239 = 1240 = Fly at the player like a missile 1241 = 1242 ================== 1243 */ 1244 1245 #define SKULLSPEED (40*FRACUNIT) 1246 1247 void A_SkullAttack (mobj_t *actor) // 80012528 1248 { 1249 mobj_t *dest; 1250 angle_t an; 1251 int dist; 1252 1253 if (!actor->target) 1254 return; 1255 1256 dest = actor->target; 1257 actor->flags |= MF_SKULLFLY; 1258 1259 S_StartSound (actor, actor->info->attacksound); 1260 A_FaceTarget (actor); 1261 an = actor->angle >> ANGLETOFINESHIFT; 1262 actor->momx = (finecosine[an] * (SKULLSPEED/FRACUNIT)); 1263 actor->momy = (finesine[an] * (SKULLSPEED/FRACUNIT)); 1264 dist = P_AproxDistance (dest->x - actor->x, dest->y - actor->y); 1265 dist = dist / SKULLSPEED; 1266 if (dist < 1) 1267 dist = 1; 1268 actor->momz = (dest->z+(dest->height>>1) - actor->z) / dist; 1269 } 1270 1271 1272 /* 1273 ============== 1274 = 1275 = PIT_PainCheckLine 1276 = 1277 ============== 1278 */ 1279 boolean PIT_PainCheckLine(intercept_t *in) // 80012654 1280 { 1281 if (!(in->d.line->backsector)) 1282 return false; 1283 1284 return true; 1285 } 1286 1287 /* 1288 ============== 1289 = 1290 = A_PainShootSkull 1291 = 1292 ============== 1293 */ 1294 1295 void A_PainShootSkull(mobj_t *actor, angle_t angle) // 8001267C 1296 { 1297 fixed_t x; 1298 fixed_t y; 1299 fixed_t z; 1300 1301 mobj_t* newmobj; 1302 angle_t an; 1303 int prestep; 1304 int count; 1305 1306 mobj_t *mo; 1307 1308 // count total number of skull currently on the level 1309 count = 0; 1310 for (mo=mobjhead.next ; mo != &mobjhead ; mo=mo->next) 1311 { 1312 if ((mo->type == MT_SKULL)) 1313 { 1314 count++; 1315 1316 // if there are allready 17 skulls on the level, 1317 // don't spit another one 1318 if (count >= 17) 1319 return; 1320 } 1321 } 1322 1323 // okay, there's playe for another one 1324 an = angle >> ANGLETOFINESHIFT; 1325 1326 prestep = (mobjinfo[MT_SKULL].radius + (4 * FRACUNIT) + actor->info->radius) >> FRACBITS; 1327 1328 x = actor->x + (finecosine[an] * prestep); 1329 y = actor->y + (finesine[an] * prestep); 1330 z = actor->z + 16 * FRACUNIT; 1331 1332 newmobj = P_SpawnMobj(x, y, z, MT_SKULL); 1333 1334 // Check for movements. 1335 if (!P_PathTraverse(actor->x, actor->y, newmobj->x, newmobj->y, PT_ADDLINES, PIT_PainCheckLine) || 1336 !P_TryMove(newmobj, newmobj->x, newmobj->y)) 1337 { 1338 // kill it immediately 1339 P_DamageMobj(newmobj, actor, actor, 10000); 1340 P_RadiusAttack(newmobj, newmobj, 128); 1341 return; 1342 } 1343 1344 newmobj->target = actor->target; 1345 P_SetMobjState(newmobj,newmobj->info->missilestate); 1346 A_SkullAttack(newmobj); 1347 } 1348 1349 /* 1350 ============== 1351 = 1352 = A_PainAttack 1353 = 1354 ============== 1355 */ 1356 1357 void A_PainAttack(mobj_t *actor) // 80012804 1358 { 1359 if (!actor->target) 1360 return; 1361 1362 A_FaceTarget(actor); 1363 A_PainShootSkull(actor, actor->angle-0x15550000); 1364 A_PainShootSkull(actor, actor->angle+0x15550000); 1365 } 1366 1367 /* 1368 ============== 1369 = 1370 = A_PainDie 1371 = 1372 ============== 1373 */ 1374 1375 void A_PainDie(mobj_t *actor) // 8001285C 1376 { 1377 A_Fall(actor); 1378 A_PainShootSkull(actor, actor->angle + ANG90); 1379 A_PainShootSkull(actor, actor->angle + ANG180); 1380 A_PainShootSkull(actor, actor->angle + ANG270); 1381 1382 A_OnDeathTrigger(actor); 1383 } 1384 1385 1386 /* 1387 ============== 1388 = 1389 = A_RectChase 1390 = 1391 ============== 1392 */ 1393 1394 void A_RectChase(mobj_t* actor) // 800128C4 1395 { 1396 if(!(actor->target) || (actor->target->health <= 0) || 1397 !(P_AproxDistance(actor->target->x-actor->x, actor->target->y-actor->y) < (600*FRACUNIT))) 1398 { 1399 A_Chase(actor); 1400 return; 1401 } 1402 1403 A_FaceTarget(actor); 1404 S_StartSound(NULL, actor->info->attacksound); 1405 P_SetMobjState(actor, actor->info->meleestate); 1406 1407 } 1408 1409 /* 1410 ============== 1411 = 1412 = A_RectGroundFire 1413 = 1414 ============== 1415 */ 1416 1417 void A_RectGroundFire(mobj_t* actor) // 8001296C 1418 { 1419 mobj_t* mo; 1420 angle_t an; 1421 1422 A_FaceTarget(actor); 1423 1424 mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PROJ_RECTFIRE); 1425 mo->target = actor; 1426 an = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); 1427 1428 mo->angle = an; 1429 mo->momx = finecosine[mo->angle >> ANGLETOFINESHIFT] * mo->info->speed; 1430 mo->momy = finesine[mo->angle >> ANGLETOFINESHIFT] * mo->info->speed; 1431 1432 mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PROJ_RECTFIRE); 1433 mo->target = actor; 1434 mo->angle = an - ANG45; 1435 mo->momx = finecosine[mo->angle >> ANGLETOFINESHIFT] * mo->info->speed; 1436 mo->momy = finesine[mo->angle >> ANGLETOFINESHIFT] * mo->info->speed; 1437 1438 mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PROJ_RECTFIRE); 1439 mo->target = actor; 1440 mo->angle = an + ANG45; 1441 mo->momx = finecosine[mo->angle >> ANGLETOFINESHIFT] * mo->info->speed; 1442 mo->momy = finesine[mo->angle >> ANGLETOFINESHIFT] * mo->info->speed; 1443 1444 S_StartSound(mo, mo->info->seesound); 1445 } 1446 1447 /* 1448 ============== 1449 = 1450 = A_RectMissile 1451 = 1452 ============== 1453 */ 1454 1455 void A_RectMissile(mobj_t* actor) // 80012B1C 1456 { 1457 mobj_t* mo; 1458 int count; 1459 angle_t an; 1460 fixed_t x; 1461 fixed_t y; 1462 fixed_t speed; 1463 1464 if(!actor->target) 1465 return; 1466 1467 A_FaceTarget(actor); 1468 for(mo = mobjhead.next; mo != &mobjhead; mo = mo->next) 1469 { 1470 // not a rect projectile 1471 if(mo->type == MT_PROJ_RECT) 1472 { 1473 if((++count >= 9)) 1474 return; 1475 } 1476 } 1477 1478 // Arm 1 1479 1480 an = (actor->angle/*-ANG90*/) >> ANGLETOFINESHIFT; 1481 x = (finesine[an] * 68); 1482 y = (finecosine[an] * 68); 1483 mo = P_SpawnMobj(actor->x + x, actor->y - y, actor->z + (68*FRACUNIT), MT_PROJ_RECT); 1484 mo->target = actor; 1485 mo->tracer = actor->target; 1486 mo->threshold = 5; 1487 an = (actor->angle + ANG270); 1488 mo->angle = an; 1489 an >>= ANGLETOFINESHIFT; 1490 speed = mo->info->speed >> 1; 1491 if(!(speed >= 0)) 1492 { 1493 speed = (mo->info->speed + 1) >> 1; 1494 } 1495 mo->momx = (finecosine[an] * speed); 1496 mo->momy = (finesine[an] * speed); 1497 1498 // Arm2 1499 1500 an = (actor->angle/*-ANG90*/) >> ANGLETOFINESHIFT; 1501 x = (finesine[an] * 50); 1502 y = (finecosine[an] * 50); 1503 mo = P_SpawnMobj(actor->x + x, actor->y - y, actor->z + (139*FRACUNIT), MT_PROJ_RECT); 1504 mo->target = actor; 1505 mo->tracer = actor->target; 1506 mo->threshold = 1; 1507 an = (actor->angle + ANG270); 1508 mo->angle = an; 1509 an >>= ANGLETOFINESHIFT; 1510 speed = mo->info->speed >> 1; 1511 if(!(speed >= 0)) 1512 { 1513 speed = (mo->info->speed + 1) >> 1; 1514 } 1515 mo->momx = (finecosine[an] * speed); 1516 mo->momy = (finesine[an] * speed); 1517 1518 // Arm3 1519 1520 an = (actor->angle/*+ANG90*/) >> ANGLETOFINESHIFT; 1521 x = (finesine[an] * 68); 1522 y = (finecosine[an] * 68); 1523 mo = P_SpawnMobj(actor->x - x, actor->y + y, actor->z + (68*FRACUNIT), MT_PROJ_RECT); 1524 mo->target = actor; 1525 mo->tracer = actor->target; 1526 mo->threshold = 5; 1527 an = (actor->angle - ANG270); 1528 mo->angle = an; 1529 an >>= ANGLETOFINESHIFT; 1530 speed = mo->info->speed >> 1; 1531 if(!(speed >= 0)) 1532 { 1533 speed = (mo->info->speed + 1) >> 1; 1534 } 1535 mo->momx = (finecosine[an] * speed); 1536 mo->momy = (finesine[an] * speed); 1537 1538 // Arm4 1539 1540 an = (actor->angle/*+ANG90*/) >> ANGLETOFINESHIFT; 1541 x = (finesine[an] * 50); 1542 y = (finecosine[an] * 50); 1543 mo = P_SpawnMobj(actor->x - x, actor->y + y, actor->z + (139*FRACUNIT), MT_PROJ_RECT); 1544 mo->target = actor; 1545 mo->tracer = actor->target; 1546 mo->threshold = 1; 1547 an = (actor->angle - ANG270); 1548 mo->angle = an; 1549 an >>= ANGLETOFINESHIFT; 1550 speed = mo->info->speed >> 1; 1551 if(!(speed >= 0)) 1552 { 1553 speed = (mo->info->speed + 1) >> 1; 1554 } 1555 mo->momx = (finecosine[an] * speed); 1556 mo->momy = (finesine[an] * speed); 1557 } 1558 1559 /* 1560 ============== 1561 = 1562 = A_MoveGroundFire 1563 = 1564 ============== 1565 */ 1566 1567 void A_MoveGroundFire(mobj_t* fire) // 80012EA4 1568 { 1569 mobj_t* mo; 1570 fade_t *fade; 1571 1572 mo = P_SpawnMobj(fire->x, fire->y, fire->floorz, MT_PROP_FIRE); 1573 1574 //P_FadeMobj(mo, -8, 0, mobjflag_t::MF_NONE); 1575 fade = Z_Malloc (sizeof(*fade), PU_LEVSPEC, 0); 1576 P_AddThinker (&fade->thinker); 1577 fade->thinker.function = T_FadeThinker; 1578 fade->amount = -8; 1579 fade->destAlpha = 0; 1580 fade->flagReserve = 0; 1581 fade->mobj = mo; 1582 } 1583 1584 /* 1585 ============== 1586 = 1587 = A_RectTracer 1588 = 1589 ============== 1590 */ 1591 1592 void A_RectTracer(mobj_t* actor) // 80012F34 1593 { 1594 if(actor->threshold < 0) 1595 A_Tracer(actor); 1596 else 1597 actor->threshold--; 1598 } 1599 1600 1601 /* 1602 ============== 1603 = 1604 = A_RectDeathEvent 1605 = 1606 ============== 1607 */ 1608 1609 void A_RectDeathEvent(mobj_t* actor) // 80012F6C 1610 { 1611 mobjexp_t *exp; 1612 1613 //P_BossExplode(actor, 3, 32); 1614 exp = Z_Malloc (sizeof(*exp), PU_LEVSPEC, 0); 1615 P_AddThinker (&exp->thinker); 1616 exp->thinker.function = T_MobjExplode; 1617 exp->mobj = actor; 1618 exp->delay = 0; 1619 exp->delaydefault = 3; 1620 exp->lifetime = 32; 1621 S_StartSound(NULL, actor->info->deathsound); 1622 } 1623 1624 1625 /* 1626 ================== 1627 = 1628 = A_TargetCamera 1629 = 1630 ================== 1631 */ 1632 1633 void A_TargetCamera(mobj_t* actor) // 80012FEC 1634 { 1635 mobj_t* mo; 1636 1637 actor->threshold = MAXINT; 1638 1639 for(mo = mobjhead.next; mo != &mobjhead; mo = mo->next) 1640 { 1641 if(actor->tid+1 == mo->tid) 1642 { 1643 actor->target = mo; 1644 P_SetMobjState(actor, actor->info->missilestate); 1645 return; 1646 } 1647 } 1648 } 1649 1650 /* 1651 ================== 1652 = 1653 = A_BarrelExplode 1654 = 1655 ================== 1656 */ 1657 1658 void A_BarrelExplode(mobj_t* actor) // 80013070 1659 { 1660 1661 S_StartSound(actor, actor->info->deathsound); 1662 P_SpawnMobj(actor->x, actor->y, actor->z + (actor->info->height >> 1), MT_EXPLOSION1); 1663 P_RadiusAttack(actor, actor->target, 128);//A_Explode(actor); 1664 1665 A_OnDeathTrigger(actor); 1666 } 1667 1668 1669 /* 1670 ================ 1671 = 1672 = A_Hoof 1673 = 1674 ================ 1675 */ 1676 1677 void A_Hoof (mobj_t *mo) // 800130E0 1678 { 1679 S_StartSound(mo, sfx_cybhoof); 1680 A_Chase(mo); 1681 } 1682 1683 /* 1684 ================ 1685 = 1686 = A_Metal 1687 = 1688 ================ 1689 */ 1690 1691 void A_Metal (mobj_t *mo) // 80013110 1692 { 1693 S_StartSound(mo, sfx_metal); 1694 A_Chase(mo); 1695 } 1696 1697 /* 1698 ================ 1699 = 1700 = A_BabyMetal 1701 = 1702 ================ 1703 */ 1704 1705 void A_BabyMetal(mobj_t* mo) // 80013140 1706 { 1707 S_StartSound(mo, sfx_bspistomp); 1708 A_Chase(mo); 1709 } 1710 1711 /*============================================================================= */ 1712 1713 /* a move in p_base.c crossed a special line */ 1714 #if 0 1715 void L_CrossSpecial (mobj_t *mo) 1716 { 1717 line_t *line; 1718 1719 line = (line_t *)(mo->extradata & ~1); 1720 1721 P_CrossSpecialLine (line, mo); 1722 } 1723 #endif 1724 1725 /* 1726 ================ 1727 = 1728 = L_MissileHit 1729 = 1730 ================ 1731 */ 1732 1733 /* a move in p_base.c caused a missile to hit another thing or wall */ 1734 void L_MissileHit (mobj_t *mo) // 80013170 1735 { 1736 int damage; 1737 mobj_t *missilething; 1738 1739 missilething = (mobj_t *)mo->extradata; 1740 damage = 0; 1741 1742 if (missilething) 1743 { 1744 damage = ((P_Random()&7)+1)*mo->info->damage; 1745 P_DamageMobj (missilething, mo, mo->target, damage); 1746 1747 if ((mo->type == MT_PROJ_RECTFIRE) && (missilething->player)) 1748 { 1749 missilething->momz = (1500*FRACUNIT) / missilething->info->mass; 1750 } 1751 } 1752 1753 if (mo->type == MT_PROJ_DART) 1754 { 1755 if (missilething && !(missilething->flags & MF_NOBLOOD)) 1756 { 1757 P_SpawnBlood(mo->x, mo->y, mo->z, damage); 1758 } 1759 else 1760 { 1761 S_StartSound(mo, sfx_darthit); 1762 P_SpawnPuff(mo->x, mo->y, mo->z); 1763 } 1764 } 1765 P_ExplodeMissile (mo); 1766 } 1767 1768 /* 1769 ================ 1770 = 1771 = L_SkullBash 1772 = 1773 ================ 1774 */ 1775 1776 /* a move in p_base.c caused a flying skull to hit another thing or a wall */ 1777 void L_SkullBash (mobj_t *mo) // 800132AC 1778 { 1779 int damage; 1780 mobj_t *skullthing; 1781 1782 skullthing = (mobj_t *)mo->extradata; 1783 1784 if (skullthing) 1785 { 1786 damage = ((P_Random()&7)+1)*mo->info->damage; 1787 P_DamageMobj (skullthing, mo, mo, damage); 1788 } 1789 1790 mo->flags &= ~MF_SKULLFLY; 1791 mo->momx = mo->momy = mo->momz = 0; 1792 P_SetMobjState (mo, mo->info->spawnstate); 1793 } 1794 1795 /* 1796 ================== 1797 = 1798 = A_FadeAlpha 1799 = 1800 ================== 1801 */ 1802 1803 void A_FadeAlpha(mobj_t *mobj) // 8001333C 1804 { 1805 int fade; 1806 1807 fade = mobj->alpha * 3; 1808 if(!(fade >= 0)) 1809 { 1810 fade = fade + 3; 1811 } 1812 1813 mobj->alpha = (fade >> 2); 1814 } 1815 1816 /* 1817 ================== 1818 = 1819 = A_PainDeathEvent 1820 = 1821 ================== 1822 */ 1823 1824 void A_PainDeathEvent(mobj_t* actor) // 80013364 1825 { 1826 actor->alpha -= 0x40; 1827 } 1828 1829 /* 1830 ================== 1831 = 1832 = A_SkullSetAlpha 1833 = 1834 ================== 1835 */ 1836 1837 void A_SkullSetAlpha(mobj_t* actor) // 80013378 1838 { 1839 actor->alpha >>= 2; 1840 } 1841 1842 /* 1843 ================== 1844 = 1845 = A_MissileSetAlpha 1846 = 1847 ================== 1848 */ 1849 1850 void A_MissileSetAlpha(mobj_t* actor) // 8001338C 1851 { 1852 actor->alpha >>= 1; 1853 } 1854 1855 1856 /* 1857 ================== 1858 = 1859 = A_FadeOut 1860 = 1861 ================== 1862 */ 1863 1864 void A_FadeOut(mobj_t* actor) // 800133A0 1865 { 1866 fade_t *fade; 1867 1868 if (actor->alpha >= 0xff) 1869 { 1870 actor->flags |= MF_SHADOW; 1871 //P_FadeMobj(actor, -8, 0x30, mobjflag_t::MF_NONE); 1872 fade = Z_Malloc (sizeof(*fade), PU_LEVSPEC, 0); 1873 P_AddThinker (&fade->thinker); 1874 fade->thinker.function = T_FadeThinker; 1875 fade->amount = -8; 1876 fade->destAlpha = 0x30; 1877 fade->flagReserve = 0; 1878 fade->mobj = actor; 1879 } 1880 } 1881 1882 1883 /* 1884 ================== 1885 = 1886 = A_FadeIn 1887 = 1888 ================== 1889 */ 1890 1891 void A_FadeIn(mobj_t* actor) // 80013428 1892 { 1893 fade_t *fade; 1894 1895 if (actor->alpha < 0xff) 1896 { 1897 actor->alpha = 0x30; 1898 actor->flags &= ~MF_SHADOW; 1899 1900 //P_FadeMobj(actor, 8, 0xff, mobjflag_t::MF_NONE); 1901 fade = Z_Malloc (sizeof(*fade), PU_LEVSPEC, 0); 1902 P_AddThinker (&fade->thinker); 1903 fade->thinker.function = T_FadeThinker; 1904 fade->mobj = actor; 1905 fade->amount = 8; 1906 fade->destAlpha = 0xff; 1907 fade->flagReserve = 0; 1908 } 1909 } 1910 1911 1912 /* 1913 ================ 1914 = 1915 P_MissileAttack 1916 = 1917 ================ 1918 */ 1919 1920 mobj_t* P_MissileAttack(mobj_t *actor, dirproj_e direction) // 800134BC 1921 { 1922 angle_t angle; 1923 fixed_t deltax, deltay, deltaz; 1924 fixed_t x, y; 1925 mobjtype_t type; 1926 mobj_t *mo; 1927 1928 if(direction == DP_LEFT) 1929 { 1930 angle = actor->angle + ANG45; 1931 } 1932 else if(direction == DP_RIGHT) 1933 { 1934 angle = actor->angle - ANG45; 1935 } 1936 else 1937 { 1938 angle = actor->angle; 1939 } 1940 1941 angle >>= ANGLETOFINESHIFT; 1942 x = finecosine[angle]; 1943 y = finesine[angle]; 1944 1945 switch(actor->type) 1946 { 1947 case MT_MANCUBUS: 1948 deltay = (y * 50); 1949 deltax = (x * 50); 1950 deltaz = (69*FRACUNIT); 1951 type = MT_PROJ_FATSO; 1952 break; 1953 case MT_IMP1: 1954 deltay = 0; 1955 deltax = 0; 1956 deltaz = (64*FRACUNIT); 1957 type = MT_PROJ_IMP1; 1958 break; 1959 case MT_IMP2: 1960 deltay = 0; 1961 deltax = 0; 1962 deltaz = (64*FRACUNIT); 1963 type = MT_PROJ_IMP2; 1964 break; 1965 case MT_CACODEMON: 1966 deltay = 0; 1967 deltax = 0; 1968 deltaz = (46*FRACUNIT); 1969 type = MT_PROJ_HEAD; 1970 break; 1971 case MT_BRUISER1: 1972 deltay = 0; 1973 deltax = 0; 1974 deltaz = (48*FRACUNIT); 1975 type = MT_PROJ_BRUISER2; 1976 break; 1977 case MT_BRUISER2: 1978 deltay = 0; 1979 deltax = 0; 1980 deltaz = (48*FRACUNIT); 1981 type = MT_PROJ_BRUISER1; 1982 break; 1983 case MT_BABY: 1984 deltay = (y * 20); 1985 deltax = (x * 20); 1986 deltaz = (28*FRACUNIT); 1987 type = MT_PROJ_BABY; 1988 break; 1989 case MT_CYBORG: 1990 case MT_CYBORG_TITLE: 1991 deltay = (y * 45); 1992 deltax = (x * 45); 1993 deltaz = (88*FRACUNIT); 1994 type = MT_PROJ_ROCKET; 1995 break; 1996 1997 default: 1998 break; 1999 } 2000 2001 mo = P_SpawnMissile(actor, actor->target, deltax, deltay, deltaz, type); 2002 return mo; 2003 }