p_enemy.c (26494B)
1 #include <stdlib.h> 2 3 #include "m_random.h" 4 #include "i_system.h" 5 #include "doomdef.h" 6 #include "p_local.h" 7 #include "s_sound.h" 8 #include "g_game.h" 9 #include "doomstat.h" 10 #include "r_state.h" 11 #include "sounds.h" 12 13 #define FATSPREAD (ANG90/8) 14 #define MAXSPECIALCROSS 8 15 #define SKULLSPEED (20*FRACUNIT) 16 17 typedef enum { 18 DI_EAST, 19 DI_NORTHEAST, 20 DI_NORTH, 21 DI_NORTHWEST, 22 DI_WEST, 23 DI_SOUTHWEST, 24 DI_SOUTH, 25 DI_SOUTHEAST, 26 DI_NODIR, 27 NUMDIRS 28 } dirtype_t; 29 30 extern line_t* spechit[MAXSPECIALCROSS]; 31 extern int numspechit; 32 mobj_t* corpsehit; 33 mobj_t* vileobj; 34 mobj_t* braintargets[32]; 35 fixed_t viletryx; 36 fixed_t viletryy; 37 int numbraintargets; 38 int braintargeton; 39 int TRACEANGLE = 0xc000000; 40 fixed_t xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000}; 41 fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000}; 42 dirtype_t opposite[] = { 43 DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, 44 DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_NODIR 45 }; 46 dirtype_t diags[] = { 47 DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST 48 }; 49 50 51 void A_Fall (mobj_t *actor); 52 void A_SpawnFly (mobj_t* mo); 53 54 mobj_t* soundtarget; 55 56 void 57 P_RecursiveSound(sector_t* sec, int soundblocks) 58 { 59 sector_t* other; 60 line_t* check; 61 int i; 62 63 if (sec->validcount == validcount && sec->soundtraversed <= soundblocks+1) return; 64 sec->validcount = validcount; 65 sec->soundtraversed = soundblocks+1; 66 sec->soundtarget = soundtarget; 67 for (i = 0; i < sec->linecount; ++i) { 68 check = sec->lines[i]; 69 if (!(check->flags & ML_TWOSIDED)) continue; 70 P_LineOpening(check); 71 if (openrange <= 0) continue; 72 if (sides[check->sidenum[0]].sector == sec) other = sides[check->sidenum[1]].sector; 73 else other = sides[ check->sidenum[0] ].sector; 74 if (check->flags & ML_SOUNDBLOCK) { 75 if (!soundblocks) 76 P_RecursiveSound (other, 1); 77 } else P_RecursiveSound (other, soundblocks); 78 } 79 } 80 81 void 82 P_NoiseAlert(mobj_t* target, mobj_t* emmiter) 83 { 84 soundtarget = target; 85 validcount++; 86 P_RecursiveSound(emmiter->subsector->sector, 0); 87 } 88 89 boolean 90 P_CheckMeleeRange(mobj_t* actor) 91 { 92 mobj_t* pl; 93 fixed_t dist; 94 95 if (!actor->target) return false; 96 pl = actor->target; 97 dist = P_AproxDistance (pl->x-actor->x, pl->y-actor->y); 98 if (dist >= MELEERANGE-20*FRACUNIT+pl->info->radius) return false; 99 if (!P_CheckSight (actor, actor->target)) return false; 100 return true; 101 } 102 103 boolean 104 P_CheckMissileRange(mobj_t* actor) 105 { 106 fixed_t dist; 107 108 if (!P_CheckSight(actor, actor->target)) return false; 109 if (actor->flags & MF_JUSTHIT) { 110 actor->flags &= ~MF_JUSTHIT; 111 return true; 112 } 113 if (actor->reactiontime) return false; 114 dist = P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) - 64*FRACUNIT; 115 if (!actor->info->meleestate) dist -= 128*FRACUNIT; 116 dist >>= 16; 117 if (actor->type == MT_VILE) 118 if (dist > 14*64) return false; 119 if (actor->type == MT_UNDEAD) { 120 if (dist < 196) return false; 121 dist >>= 1; 122 } 123 if (actor->type == MT_CYBORG || actor->type == MT_SPIDER || actor->type == MT_SKULL) dist >>= 1; 124 if (dist > 200) dist = 200; 125 if (actor->type == MT_CYBORG && dist > 160) dist = 160; 126 if (P_Random() < dist) return false; 127 return true; 128 } 129 130 boolean 131 P_Move(mobj_t* actor) 132 { 133 line_t* ld; 134 fixed_t tryx, tryy; 135 boolean good, try_ok; 136 137 if (actor->movedir == DI_NODIR) return false; 138 if ((unsigned)actor->movedir >= 8) I_Error("Weird actor->movedir!"); 139 tryx = actor->x + actor->info->speed*xspeed[actor->movedir]; 140 tryy = actor->y + actor->info->speed*yspeed[actor->movedir]; 141 try_ok = P_TryMove (actor, tryx, tryy); 142 if (!try_ok) { 143 if (actor->flags & MF_FLOAT && floatok) { 144 if (actor->z < tmfloorz) actor->z += FLOATSPEED; 145 else actor->z -= FLOATSPEED; 146 actor->flags |= MF_INFLOAT; 147 return true; 148 } 149 if (!numspechit) return false; 150 actor->movedir = DI_NODIR; 151 good = false; 152 while (numspechit--) { 153 ld = spechit[numspechit]; 154 if (P_UseSpecialLine (actor, ld,0)) good = true; 155 } 156 return good; 157 } else actor->flags &= ~MF_INFLOAT; 158 if (! (actor->flags & MF_FLOAT) ) actor->z = actor->floorz; 159 return true; 160 } 161 162 boolean 163 P_TryWalk(mobj_t* actor) 164 { 165 if (!P_Move(actor)) return false; 166 actor->movecount = P_Random() & 15; 167 return true; 168 } 169 170 void 171 P_NewChaseDir(mobj_t* actor) 172 { 173 fixed_t deltax; 174 fixed_t deltay; 175 dirtype_t olddir, turnaround, d[3]; 176 int tdir; 177 178 if (!actor->target) I_Error("P_NewChaseDir: called with no target"); 179 olddir = actor->movedir; 180 turnaround=opposite[olddir]; 181 deltax = actor->target->x - actor->x; 182 deltay = actor->target->y - actor->y; 183 if (deltax>10*FRACUNIT) d[1] = DI_EAST; 184 else if (deltax<-10*FRACUNIT) d[1] = DI_WEST; 185 else d[1] =DI_NODIR; 186 if (deltay<-10*FRACUNIT) d[2] = DI_SOUTH; 187 else if (deltay>10*FRACUNIT) d[2] = DI_NORTH; 188 else d[2] = DI_NODIR; 189 if (d[1] != DI_NODIR && d[2] != DI_NODIR) { 190 actor->movedir = diags[((deltay<0) << 1) + (deltax > 0)]; 191 if (actor->movedir != turnaround && P_TryWalk(actor)) return; 192 } 193 if (P_Random() > 200 || abs(deltay)>abs(deltax)) { 194 tdir=d[1]; 195 d[1]=d[2]; 196 d[2]=tdir; 197 } 198 if (d[1]==turnaround) d[1]=DI_NODIR; 199 if (d[2]==turnaround) d[2]=DI_NODIR; 200 if (d[1]!=DI_NODIR) { 201 actor->movedir = d[1]; 202 if (P_TryWalk(actor)) return; 203 } 204 if (d[2]!=DI_NODIR) { 205 actor->movedir =d[2]; 206 if (P_TryWalk(actor)) return; 207 } 208 if (olddir!=DI_NODIR) { 209 actor->movedir = olddir; 210 if (P_TryWalk(actor)) return; 211 } 212 if (P_Random() & 1) { 213 for (tdir=DI_EAST; tdir<=DI_SOUTHEAST; ++tdir) { 214 if (tdir!=turnaround) { 215 actor->movedir =tdir; 216 if (P_TryWalk(actor)) return; 217 } 218 } 219 } else { 220 for (tdir=DI_SOUTHEAST; tdir != (DI_EAST-1); --tdir) { 221 if (tdir!=turnaround) { 222 actor->movedir =tdir; 223 if (P_TryWalk(actor)) return; 224 } 225 } 226 } 227 if (turnaround != DI_NODIR) { 228 actor->movedir =turnaround; 229 if (P_TryWalk(actor)) return; 230 } 231 actor->movedir = DI_NODIR; 232 } 233 234 boolean 235 P_LookForPlayers(mobj_t* actor, boolean allaround) 236 { 237 player_t* player; 238 angle_t an; 239 fixed_t dist; 240 int c, stop; 241 242 c = 0; 243 stop = (actor->lastlook-1) & 3; 244 for (;; actor->lastlook = (actor->lastlook+1)&3) { 245 if (!playeringame[actor->lastlook]) continue; 246 if (c++ == 2 || actor->lastlook == stop) return false; 247 player = &players[actor->lastlook]; 248 if (player->health <= 0) continue; 249 if (!P_CheckSight (actor, player->mo)) continue; 250 if (!allaround) { 251 an = R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y) - actor->angle; 252 if (an > ANG90 && an < ANG270) { 253 dist = P_AproxDistance (player->mo->x - actor->x, player->mo->y - actor->y); 254 if (dist > MELEERANGE) continue; 255 } 256 } 257 actor->target = player->mo; 258 return true; 259 } 260 return false; 261 } 262 263 void 264 A_KeenDie(mobj_t* mo) 265 { 266 thinker_t* th; 267 mobj_t* mo2; 268 line_t junk; 269 270 A_Fall(mo); 271 for (th = thinkercap.next; th != &thinkercap; th = th->next) { 272 if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; 273 mo2 = (mobj_t *)th; 274 if (mo2 != mo && mo2->type == mo->type && mo2->health > 0) return; 275 } 276 junk.tag = 666; 277 EV_DoDoor(&junk, open); 278 } 279 280 void 281 A_Look (mobj_t* actor) 282 { 283 mobj_t* targ; 284 int sound; 285 286 actor->threshold = 0; 287 targ = actor->subsector->sector->soundtarget; 288 if (targ && (targ->flags & MF_SHOOTABLE)) { 289 actor->target = targ; 290 if (actor->flags & MF_AMBUSH) { 291 if (P_CheckSight (actor, actor->target)) 292 goto seeyou; 293 } else goto seeyou; 294 if (!P_LookForPlayers (actor, false)) return; 295 seeyou: 296 if (actor->info->seesound) { 297 switch (actor->info->seesound) { 298 case sfx_posit1: 299 case sfx_posit2: 300 case sfx_posit3: 301 sound = sfx_posit1+P_Random()%3; 302 break; 303 case sfx_bgsit1: 304 case sfx_bgsit2: 305 sound = sfx_bgsit1+P_Random()%2; 306 break; 307 default: 308 sound = actor->info->seesound; 309 break; 310 } 311 if (actor->type==MT_SPIDER || actor->type == MT_CYBORG) S_StartSound (NULL, sound); 312 else S_StartSound (actor, sound); 313 } 314 P_SetMobjState (actor, actor->info->seestate); 315 } 316 } 317 318 void 319 A_Chase(mobj_t* actor) 320 { 321 int delta; 322 323 if (actor->reactiontime) --actor->reactiontime; 324 if (actor->threshold) { 325 if (!actor->target || actor->target->health <= 0) actor->threshold = 0; 326 else actor->threshold--; 327 } 328 if (actor->movedir < 8) { 329 actor->angle &= (7<<29); 330 delta = actor->angle - (actor->movedir << 29); 331 if (delta > 0) actor->angle -= ANG90/2; 332 if (delta < 0) actor->angle += ANG90/2; 333 } 334 if (!actor->target || !(actor->target->flags&MF_SHOOTABLE)) { 335 if (P_LookForPlayers(actor,true)) return; 336 P_SetMobjState(actor, actor->info->spawnstate); 337 return; 338 } 339 if (actor->flags & MF_JUSTATTACKED) { 340 actor->flags &= ~MF_JUSTATTACKED; 341 if (gameskill != sk_nightmare && !fastparm) P_NewChaseDir(actor); 342 return; 343 } 344 if (actor->info->meleestate && P_CheckMeleeRange (actor)) { 345 if (actor->info->attacksound) S_StartSound (actor, actor->info->attacksound); 346 P_SetMobjState (actor, actor->info->meleestate); 347 return; 348 } 349 if (actor->info->missilestate) { 350 if (gameskill < sk_nightmare && !fastparm && actor->movecount) goto nomissile; 351 if (!P_CheckMissileRange(actor)) goto nomissile; 352 P_SetMobjState (actor, actor->info->missilestate); 353 actor->flags |= MF_JUSTATTACKED; 354 return; 355 } 356 nomissile: 357 if (netgame && !actor->threshold && !P_CheckSight (actor, actor->target)) 358 if (P_LookForPlayers(actor,true)) return; 359 if (--actor->movecount < 0 || !P_Move (actor)) 360 P_NewChaseDir (actor); 361 if (actor->info->activesound && P_Random() < 3) S_StartSound (actor, actor->info->activesound); 362 } 363 364 void 365 A_FaceTarget(mobj_t* actor) 366 { 367 if (!actor->target) return; 368 actor->flags &= ~MF_AMBUSH; 369 actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); 370 if (actor->target->flags & MF_SHADOW) actor->angle += (P_Random()-P_Random())<<21; 371 } 372 373 void 374 A_PosAttack(mobj_t* actor) 375 { 376 int angle, damage, slope; 377 378 if (!actor->target) return; 379 A_FaceTarget (actor); 380 angle = actor->angle; 381 slope = P_AimLineAttack (actor, angle, MISSILERANGE); 382 S_StartSound (actor, sfx_pistol); 383 angle += (P_Random()-P_Random())<<20; 384 damage = ((P_Random()%5)+1)*3; 385 P_LineAttack (actor, angle, MISSILERANGE, slope, damage); 386 } 387 388 void 389 A_SPosAttack(mobj_t* actor) 390 { 391 int i, angle, bangle, damage, slope; 392 393 if (!actor->target) return; 394 S_StartSound(actor, sfx_shotgn); 395 A_FaceTarget(actor); 396 bangle = actor->angle; 397 slope = P_AimLineAttack (actor, bangle, MISSILERANGE); 398 for (i = 0; i < 3; ++i) { 399 angle = bangle + ((P_Random()-P_Random()) << 20); 400 damage = ((P_Random()%5)+1)*3; 401 P_LineAttack (actor, angle, MISSILERANGE, slope, damage); 402 } 403 } 404 405 void 406 A_CPosAttack(mobj_t* actor) 407 { 408 int angle, bangle, damage, slope; 409 410 if (!actor->target) return; 411 S_StartSound(actor, sfx_shotgn); 412 A_FaceTarget(actor); 413 bangle = actor->angle; 414 slope = P_AimLineAttack(actor, bangle, MISSILERANGE); 415 angle = bangle + ((P_Random()-P_Random())<<20); 416 damage = ((P_Random()%5)+1)*3; 417 P_LineAttack (actor, angle, MISSILERANGE, slope, damage); 418 } 419 420 void 421 A_CPosRefire(mobj_t* actor) 422 { 423 A_FaceTarget(actor); 424 425 if (P_Random() < 40) return; 426 if (!actor->target || actor->target->health <= 0 || !P_CheckSight (actor, actor->target)) P_SetMobjState (actor, actor->info->seestate); 427 } 428 429 void 430 A_SpidRefire(mobj_t* actor) 431 { 432 A_FaceTarget(actor); 433 434 if (P_Random() < 10) return; 435 if (!actor->target || actor->target->health <= 0 || !P_CheckSight (actor, actor->target)) P_SetMobjState (actor, actor->info->seestate); 436 } 437 438 void 439 A_BspiAttack(mobj_t *actor) 440 { 441 if (!actor->target) return; 442 A_FaceTarget (actor); 443 P_SpawnMissile (actor, actor->target, MT_ARACHPLAZ); 444 } 445 446 void 447 A_TroopAttack(mobj_t* actor) 448 { 449 int damage; 450 451 if (!actor->target) return; 452 A_FaceTarget (actor); 453 if (P_CheckMeleeRange (actor)) { 454 S_StartSound (actor, sfx_claw); 455 damage = (P_Random()%8+1)*3; 456 P_DamageMobj (actor->target, actor, actor, damage); 457 return; 458 } 459 P_SpawnMissile (actor, actor->target, MT_TROOPSHOT); 460 } 461 462 void 463 A_SargAttack(mobj_t* actor) 464 { 465 int damage; 466 467 if (!actor->target) return; 468 A_FaceTarget(actor); 469 if (P_CheckMeleeRange (actor)) { 470 damage = ((P_Random()%10)+1)*4; 471 P_DamageMobj (actor->target, actor, actor, damage); 472 } 473 } 474 475 void 476 A_HeadAttack(mobj_t* actor) 477 { 478 int damage; 479 480 if (!actor->target) return; 481 A_FaceTarget(actor); 482 if (P_CheckMeleeRange (actor)) { 483 damage = (P_Random()%6+1)*10; 484 P_DamageMobj (actor->target, actor, actor, damage); 485 return; 486 } 487 P_SpawnMissile (actor, actor->target, MT_HEADSHOT); 488 } 489 490 void 491 A_CyberAttack(mobj_t* actor) 492 { 493 if (!actor->target) return; 494 A_FaceTarget (actor); 495 P_SpawnMissile (actor, actor->target, MT_ROCKET); 496 } 497 498 void 499 A_BruisAttack(mobj_t* actor) 500 { 501 int damage; 502 503 if (!actor->target) return; 504 if (P_CheckMeleeRange (actor)) { 505 S_StartSound (actor, sfx_claw); 506 damage = (P_Random()%8+1)*10; 507 P_DamageMobj (actor->target, actor, actor, damage); 508 return; 509 } 510 P_SpawnMissile (actor, actor->target, MT_BRUISERSHOT); 511 } 512 513 void 514 A_SkelMissile(mobj_t* actor) 515 { 516 mobj_t* mo; 517 518 if (!actor->target) return; 519 A_FaceTarget (actor); 520 actor->z += 16*FRACUNIT; 521 mo = P_SpawnMissile (actor, actor->target, MT_TRACER); 522 actor->z -= 16*FRACUNIT; 523 mo->x += mo->momx; 524 mo->y += mo->momy; 525 mo->tracer = actor->target; 526 } 527 528 529 void A_Tracer (mobj_t* actor) 530 { 531 angle_t exact; 532 fixed_t dist; 533 fixed_t slope; 534 mobj_t* dest; 535 mobj_t* th; 536 537 if (gametic & 3) return; 538 P_SpawnPuff(actor->x, actor->y, actor->z); 539 th = P_SpawnMobj (actor->x-actor->momx, actor->y-actor->momy, actor->z, MT_SMOKE); 540 th->momz = FRACUNIT; 541 th->tics -= P_Random() & 3; 542 if (th->tics < 1) th->tics = 1; 543 dest = actor->tracer; 544 if (!dest || dest->health <= 0) return; 545 exact = R_PointToAngle2(actor->x, actor->y, dest->x, dest->y); 546 if (exact != actor->angle) { 547 if (exact - actor->angle > 0x80000000) { 548 actor->angle -= TRACEANGLE; 549 if (exact - actor->angle < 0x80000000) 550 actor->angle = exact; 551 } else { 552 actor->angle += TRACEANGLE; 553 if (exact - actor->angle > 0x80000000) 554 actor->angle = exact; 555 } 556 } 557 exact = actor->angle>>ANGLETOFINESHIFT; 558 actor->momx = FixedMul (actor->info->speed, finecosine[exact]); 559 actor->momy = FixedMul (actor->info->speed, finesine[exact]); 560 dist = P_AproxDistance (dest->x - actor->x, dest->y - actor->y); 561 dist = dist / actor->info->speed; 562 if (dist < 1) dist = 1; 563 slope = (dest->z+40*FRACUNIT - actor->z) / dist; 564 if (slope < actor->momz) actor->momz -= FRACUNIT/8; 565 else actor->momz += FRACUNIT/8; 566 } 567 568 void 569 A_SkelWhoosh(mobj_t* actor) 570 { 571 if (!actor->target) return; 572 A_FaceTarget (actor); 573 S_StartSound (actor,sfx_skeswg); 574 } 575 576 void 577 A_SkelFist(mobj_t* actor) 578 { 579 int damage; 580 581 if (!actor->target) return; 582 A_FaceTarget (actor); 583 if (P_CheckMeleeRange (actor)) { 584 damage = ((P_Random()%10)+1)*6; 585 S_StartSound (actor, sfx_skepch); 586 P_DamageMobj (actor->target, actor, actor, damage); 587 } 588 } 589 590 boolean 591 PIT_VileCheck(mobj_t* thing) 592 { 593 boolean check; 594 int maxdist; 595 596 if (!(thing->flags & MF_CORPSE)) return true; 597 if (thing->tics != -1) return true; 598 if (thing->info->raisestate == S_NULL) return true; 599 maxdist = thing->info->radius + mobjinfo[MT_VILE].radius; 600 if (abs(thing->x - viletryx) > maxdist || abs(thing->y - viletryy) > maxdist) return true; 601 corpsehit = thing; 602 corpsehit->momx = corpsehit->momy = 0; 603 corpsehit->height <<= 2; 604 check = P_CheckPosition (corpsehit, corpsehit->x, corpsehit->y); 605 corpsehit->height >>= 2; 606 if (!check) return true; 607 return false; 608 } 609 610 void 611 A_VileChase(mobj_t* actor) 612 { 613 mobjinfo_t* info; 614 mobj_t* temp; 615 int xl, xh, yl, yh, bx, by; 616 617 if (actor->movedir != DI_NODIR) { 618 viletryx = actor->x + actor->info->speed*xspeed[actor->movedir]; 619 viletryy = actor->y + actor->info->speed*yspeed[actor->movedir]; 620 xl = (viletryx - bmaporgx - MAXRADIUS*2)>>MAPBLOCKSHIFT; 621 xh = (viletryx - bmaporgx + MAXRADIUS*2)>>MAPBLOCKSHIFT; 622 yl = (viletryy - bmaporgy - MAXRADIUS*2)>>MAPBLOCKSHIFT; 623 yh = (viletryy - bmaporgy + MAXRADIUS*2)>>MAPBLOCKSHIFT; 624 vileobj = actor; 625 for (bx=xl ; bx<=xh ; bx++) { 626 for (by=yl ; by<=yh ; by++) { 627 if (!P_BlockThingsIterator(bx,by,PIT_VileCheck)) { 628 temp = actor->target; 629 actor->target = corpsehit; 630 A_FaceTarget (actor); 631 actor->target = temp; 632 P_SetMobjState (actor, S_VILE_HEAL1); 633 S_StartSound (corpsehit, sfx_slop); 634 info = corpsehit->info; 635 P_SetMobjState (corpsehit,info->raisestate); 636 corpsehit->height <<= 2; 637 corpsehit->flags = info->flags; 638 corpsehit->health = info->spawnhealth; 639 corpsehit->target = NULL; 640 return; 641 } 642 } 643 } 644 } 645 A_Chase (actor); 646 } 647 648 void 649 A_VileStart(mobj_t* actor) 650 { 651 S_StartSound (actor, sfx_vilatk); 652 } 653 654 void A_Fire(mobj_t* actor); 655 656 void 657 A_StartFire(mobj_t* actor) 658 { 659 S_StartSound(actor,sfx_flamst); 660 A_Fire(actor); 661 } 662 663 void 664 A_FireCrackle(mobj_t* actor) 665 { 666 S_StartSound(actor,sfx_flame); 667 A_Fire(actor); 668 } 669 670 void A_Fire (mobj_t* actor) 671 { 672 mobj_t* dest; 673 unsigned an; 674 675 dest = actor->tracer; 676 if (!dest) return; 677 if (!P_CheckSight (actor->target, dest)) return; 678 an = dest->angle >> ANGLETOFINESHIFT; 679 P_UnsetThingPosition (actor); 680 actor->x = dest->x + FixedMul (24*FRACUNIT, finecosine[an]); 681 actor->y = dest->y + FixedMul (24*FRACUNIT, finesine[an]); 682 actor->z = dest->z; 683 P_SetThingPosition (actor); 684 } 685 686 void 687 A_VileTarget(mobj_t* actor) 688 { 689 mobj_t* fog; 690 691 if (!actor->target) return; 692 A_FaceTarget (actor); 693 fog = P_SpawnMobj (actor->target->x, actor->target->x, actor->target->z, MT_FIRE); 694 actor->tracer = fog; 695 fog->target = actor; 696 fog->tracer = actor->target; 697 A_Fire (fog); 698 } 699 700 void 701 A_VileAttack(mobj_t* actor) 702 { 703 mobj_t* fire; 704 int an; 705 706 if (!actor->target) return; 707 A_FaceTarget(actor); 708 if (!P_CheckSight (actor, actor->target)) return; 709 S_StartSound (actor, sfx_barexp); 710 P_DamageMobj (actor->target, actor, actor, 20); 711 actor->target->momz = 1000*FRACUNIT/actor->target->info->mass; 712 an = actor->angle >> ANGLETOFINESHIFT; 713 fire = actor->tracer; 714 if (!fire) return; 715 fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]); 716 fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]); 717 P_RadiusAttack (fire, actor, 70 ); 718 } 719 720 721 void 722 A_FatRaise(mobj_t *actor) 723 { 724 A_FaceTarget(actor); 725 S_StartSound(actor, sfx_manatk); 726 } 727 728 void 729 A_FatAttack1(mobj_t* actor) 730 { 731 mobj_t* mo; 732 int an; 733 734 A_FaceTarget (actor); 735 actor->angle += FATSPREAD; 736 P_SpawnMissile (actor, actor->target, MT_FATSHOT); 737 mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT); 738 mo->angle += FATSPREAD; 739 an = mo->angle >> ANGLETOFINESHIFT; 740 mo->momx = FixedMul (mo->info->speed, finecosine[an]); 741 mo->momy = FixedMul (mo->info->speed, finesine[an]); 742 } 743 744 void 745 A_FatAttack2(mobj_t* actor) 746 { 747 mobj_t* mo; 748 int an; 749 750 A_FaceTarget (actor); 751 actor->angle -= FATSPREAD; 752 P_SpawnMissile (actor, actor->target, MT_FATSHOT); 753 mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT); 754 mo->angle -= FATSPREAD*2; 755 an = mo->angle >> ANGLETOFINESHIFT; 756 mo->momx = FixedMul (mo->info->speed, finecosine[an]); 757 mo->momy = FixedMul (mo->info->speed, finesine[an]); 758 } 759 760 void 761 A_FatAttack3(mobj_t* actor) 762 { 763 mobj_t* mo; 764 int an; 765 766 A_FaceTarget (actor); 767 mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT); 768 mo->angle -= FATSPREAD/2; 769 an = mo->angle >> ANGLETOFINESHIFT; 770 mo->momx = FixedMul (mo->info->speed, finecosine[an]); 771 mo->momy = FixedMul (mo->info->speed, finesine[an]); 772 mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT); 773 mo->angle += FATSPREAD/2; 774 an = mo->angle >> ANGLETOFINESHIFT; 775 mo->momx = FixedMul (mo->info->speed, finecosine[an]); 776 mo->momy = FixedMul (mo->info->speed, finesine[an]); 777 } 778 779 void A_SkullAttack (mobj_t* actor) 780 { 781 mobj_t* dest; 782 angle_t an; 783 int dist; 784 785 if (!actor->target) return; 786 dest = actor->target; 787 actor->flags |= MF_SKULLFLY; 788 S_StartSound(actor, actor->info->attacksound); 789 A_FaceTarget(actor); 790 an = actor->angle >> ANGLETOFINESHIFT; 791 actor->momx = FixedMul(SKULLSPEED, finecosine[an]); 792 actor->momy = FixedMul(SKULLSPEED, finesine[an]); 793 dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y); 794 dist = dist / SKULLSPEED; 795 if (dist < 1) dist = 1; 796 actor->momz = (dest->z+(dest->height>>1) - actor->z) / dist; 797 } 798 799 void 800 A_PainShootSkull(mobj_t* actor, angle_t angle) 801 { 802 mobj_t* newmobj; 803 thinker_t* currentthinker; 804 fixed_t x, y, z; 805 angle_t an; 806 int prestep, count; 807 808 count = 0; 809 currentthinker = thinkercap.next; 810 while (currentthinker != &thinkercap) { 811 if ((currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) && ((mobj_t*)currentthinker)->type == MT_SKULL) ++count; 812 currentthinker = currentthinker->next; 813 } 814 if (count > 20) return; 815 an = angle >> ANGLETOFINESHIFT; 816 prestep = 4 * FRACUNIT + 3 *(actor->info->radius + mobjinfo[MT_SKULL].radius)/2; 817 x = actor->x + FixedMul(prestep, finecosine[an]); 818 y = actor->y + FixedMul(prestep, finesine[an]); 819 z = actor->z + 8 * FRACUNIT; 820 newmobj = P_SpawnMobj (x, y, z, MT_SKULL); 821 if (!P_TryMove (newmobj, newmobj->x, newmobj->y)) { 822 P_DamageMobj (newmobj,actor,actor,10000); 823 return; 824 } 825 newmobj->target = actor->target; 826 A_SkullAttack (newmobj); 827 } 828 829 void 830 A_PainAttack(mobj_t* actor) 831 { 832 if (!actor->target) return; 833 A_FaceTarget(actor); 834 A_PainShootSkull(actor, actor->angle); 835 } 836 837 void 838 A_PainDie(mobj_t* actor) 839 { 840 A_Fall(actor); 841 A_PainShootSkull(actor, actor->angle+ANG90); 842 A_PainShootSkull(actor, actor->angle+ANG180); 843 A_PainShootSkull(actor, actor->angle+ANG270); 844 } 845 846 void 847 A_Scream(mobj_t* actor) 848 { 849 int sound; 850 851 switch (actor->info->deathsound) { 852 case 0: 853 return; 854 case sfx_podth1: 855 case sfx_podth2: 856 case sfx_podth3: 857 sound = sfx_podth1 + P_Random ()%3; 858 break; 859 case sfx_bgdth1: 860 case sfx_bgdth2: 861 sound = sfx_bgdth1 + P_Random ()%2; 862 break; 863 default: 864 sound = actor->info->deathsound; 865 break; 866 } 867 if (actor->type==MT_SPIDER || actor->type == MT_CYBORG) S_StartSound(NULL, sound); 868 else S_StartSound(actor, sound); 869 } 870 871 void 872 A_XScream(mobj_t* actor) 873 { 874 S_StartSound (actor, sfx_slop); 875 } 876 877 void 878 A_Pain(mobj_t* actor) 879 { 880 if (actor->info->painsound) S_StartSound(actor, actor->info->painsound); 881 } 882 883 void 884 A_Fall(mobj_t *actor) 885 { 886 actor->flags &= ~MF_SOLID; 887 } 888 889 void 890 A_Explode(mobj_t* thingy) 891 { 892 P_RadiusAttack ( thingy, thingy->target, 128 ); 893 } 894 895 void 896 A_BossDeath(mobj_t* mo) 897 { 898 thinker_t* th; 899 mobj_t* mo2; 900 line_t junk; 901 int i; 902 903 switch (gameepisode) { 904 case 1: 905 if (gamemap != 8) return; 906 if (mo->type != MT_BRUISER) return; 907 break; 908 case 2: 909 if (gamemap != 8) return; 910 if (mo->type != MT_CYBORG) return; 911 break; 912 case 3: 913 if (gamemap != 8) return; 914 if (mo->type != MT_SPIDER) return; 915 break; 916 case 4: 917 switch (gamemap) { 918 case 6: 919 if (mo->type != MT_CYBORG) 920 return; 921 break; 922 case 8: 923 if (mo->type != MT_SPIDER) 924 return; 925 break; 926 default: 927 return; 928 break; 929 } 930 break; 931 default: 932 if (gamemap != 8) return; 933 break; 934 } 935 for (i = 0; i < MAXPLAYERS; ++i) 936 if (playeringame[i] && players[i].health > 0) break; 937 if (i == MAXPLAYERS) return; 938 for (th = thinkercap.next ; th != &thinkercap ; th=th->next) { 939 if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; 940 mo2 = (mobj_t*)th; 941 if (mo2 != mo && mo2->type == mo->type && mo2->health > 0) return; 942 } 943 switch (gameepisode) { 944 case 1: 945 junk.tag = 666; 946 EV_DoFloor (&junk, lowerFloorToLowest); 947 return; 948 break; 949 case 4: 950 switch (gamemap) { 951 case 6: 952 junk.tag = 666; 953 EV_DoDoor (&junk, blazeOpen); 954 return; 955 break; 956 case 8: 957 junk.tag = 666; 958 EV_DoFloor (&junk, lowerFloorToLowest); 959 return; 960 break; 961 } 962 } 963 G_ExitLevel(); 964 } 965 966 void 967 A_Hoof(mobj_t* mo) 968 { 969 S_StartSound(mo, sfx_hoof); 970 A_Chase(mo); 971 } 972 973 void 974 A_Metal(mobj_t* mo) 975 { 976 S_StartSound(mo, sfx_metal); 977 A_Chase(mo); 978 } 979 980 void 981 A_BabyMetal(mobj_t* mo) 982 { 983 S_StartSound(mo, sfx_bspwlk); 984 A_Chase(mo); 985 } 986 987 void 988 A_OpenShotgun2(player_t* player, pspdef_t* psp) 989 { 990 S_StartSound(player->mo, sfx_dbopn); 991 } 992 993 void 994 A_LoadShotgun2(player_t* player, pspdef_t* psp) 995 { 996 S_StartSound (player->mo, sfx_dbload); 997 } 998 999 void A_ReFire(player_t* player, pspdef_t* psp); 1000 1001 void 1002 A_CloseShotgun2(player_t* player, pspdef_t* psp) 1003 { 1004 S_StartSound(player->mo, sfx_dbcls); 1005 A_ReFire(player,psp); 1006 } 1007 1008 void A_BrainAwake (mobj_t* mo) 1009 { 1010 thinker_t* thinker; 1011 mobj_t* m; 1012 1013 numbraintargets = 0; 1014 braintargeton = 0; 1015 thinker = thinkercap.next; 1016 for (thinker = thinkercap.next; thinker != &thinkercap; thinker = thinker->next) { 1017 if (thinker->function.acp1 != (actionf_p1)P_MobjThinker) continue; 1018 m = (mobj_t *)thinker; 1019 if (m->type == MT_BOSSTARGET) { 1020 braintargets[numbraintargets] = m; 1021 numbraintargets++; 1022 } 1023 } 1024 S_StartSound(NULL,sfx_bossit); 1025 } 1026 1027 void 1028 A_BrainPain(mobj_t* mo) 1029 { 1030 S_StartSound(NULL,sfx_bospn); 1031 } 1032 1033 void 1034 A_BrainScream(mobj_t* mo) 1035 { 1036 mobj_t* th; 1037 int x, y, z; 1038 1039 for (x=mo->x - 196*FRACUNIT; x < mo->x + 320*FRACUNIT; x += FRACUNIT*8) { 1040 y = mo->y - 320*FRACUNIT; 1041 z = 128 + P_Random()*2*FRACUNIT; 1042 th = P_SpawnMobj (x,y,z, MT_ROCKET); 1043 th->momz = P_Random()*512; 1044 P_SetMobjState(th, S_BRAINEXPLODE1); 1045 th->tics -= P_Random() & 7; 1046 if (th->tics < 1) th->tics = 1; 1047 } 1048 S_StartSound(NULL, sfx_bosdth); 1049 } 1050 1051 void 1052 A_BrainExplode(mobj_t* mo) 1053 { 1054 mobj_t* th; 1055 int x, y, z; 1056 1057 x = mo->x + (P_Random() - P_Random()) * 2048; 1058 y = mo->y; 1059 z = 128 + P_Random()*2*FRACUNIT; 1060 th = P_SpawnMobj (x,y,z, MT_ROCKET); 1061 th->momz = P_Random()*512; 1062 P_SetMobjState(th, S_BRAINEXPLODE1); 1063 th->tics -= P_Random() & 7; 1064 if (th->tics < 1) th->tics = 1; 1065 } 1066 1067 void 1068 A_BrainDie(mobj_t* mo) 1069 { 1070 G_ExitLevel(); 1071 } 1072 1073 1074 void 1075 A_BrainSpit(mobj_t* mo) 1076 { 1077 static int easy = 0; 1078 mobj_t* targ; 1079 mobj_t* newmobj; 1080 1081 easy ^= 1; 1082 if (gameskill <= sk_easy && (!easy)) return; 1083 targ = braintargets[braintargeton]; 1084 braintargeton = (braintargeton+1)%numbraintargets; 1085 newmobj = P_SpawnMissile(mo, targ, MT_SPAWNSHOT); 1086 newmobj->target = targ; 1087 newmobj->reactiontime = ((targ->y - mo->y)/newmobj->momy) / newmobj->state->tics; 1088 S_StartSound(NULL, sfx_bospit); 1089 } 1090 1091 void 1092 A_SpawnSound(mobj_t* mo) 1093 { 1094 S_StartSound(mo,sfx_boscub); 1095 A_SpawnFly(mo); 1096 } 1097 1098 void 1099 A_SpawnFly(mobj_t* mo) 1100 { 1101 mobj_t* newmobj, *fog, *targ; 1102 mobjtype_t type; 1103 int r; 1104 1105 if (--mo->reactiontime) return; 1106 targ = mo->target; 1107 fog = P_SpawnMobj(targ->x, targ->y, targ->z, MT_SPAWNFIRE); 1108 S_StartSound(fog, sfx_telept); 1109 r = P_Random(); 1110 if (r < 50) type = MT_TROOP; 1111 else if (r < 90) type = MT_SERGEANT; 1112 else if (r < 120) type = MT_SHADOWS; 1113 else if (r < 130) type = MT_PAIN; 1114 else if (r < 160) type = MT_HEAD; 1115 else if (r < 162) type = MT_VILE; 1116 else if (r < 172) type = MT_UNDEAD; 1117 else if (r < 192) type = MT_BABY; 1118 else if (r < 222) type = MT_FATSO; 1119 else if (r < 246) type = MT_KNIGHT; 1120 else type = MT_BRUISER; 1121 newmobj = P_SpawnMobj (targ->x, targ->y, targ->z, type); 1122 if (P_LookForPlayers (newmobj, true)) P_SetMobjState(newmobj, newmobj->info->seestate); 1123 P_TeleportMove(newmobj, newmobj->x, newmobj->y); 1124 P_RemoveMobj(mo); 1125 } 1126 1127 void 1128 A_PlayerScream(mobj_t* mo) 1129 { 1130 int sound; 1131 1132 sound = sfx_pldeth; 1133 S_StartSound(mo, sound); 1134 }