p_enemy.c
上传用户:xuyinpeng
上传日期:2021-05-12
资源大小:455k
文件大小:38k
源码类别:

射击游戏

开发平台:

Visual C++

  1. // Emacs style mode select   -*- C++ -*- 
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. // Enemy thinking, AI.
  21. // Action Pointer Functions
  22. // that are associated with states/frames. 
  23. //
  24. //-----------------------------------------------------------------------------
  25. static const char
  26. rcsid[] = "$Id: p_enemy.c,v 1.5 1997/02/03 22:45:11 b1 Exp $";
  27. #include <stdlib.h>
  28. #include "m_random.h"
  29. #include "i_system.h"
  30. #include "doomdef.h"
  31. #include "p_local.h"
  32. #include "s_sound.h"
  33. #include "g_game.h"
  34. // State.
  35. #include "doomstat.h"
  36. #include "r_state.h"
  37. // Data.
  38. #include "sounds.h"
  39. typedef enum
  40. {
  41.     DI_EAST,
  42.     DI_NORTHEAST,
  43.     DI_NORTH,
  44.     DI_NORTHWEST,
  45.     DI_WEST,
  46.     DI_SOUTHWEST,
  47.     DI_SOUTH,
  48.     DI_SOUTHEAST,
  49.     DI_NODIR,
  50.     NUMDIRS
  51.     
  52. } dirtype_t;
  53. //
  54. // P_NewChaseDir related LUT.
  55. //
  56. dirtype_t opposite[] =
  57. {
  58.   DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST,
  59.   DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_NODIR
  60. };
  61. dirtype_t diags[] =
  62. {
  63.     DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST
  64. };
  65. void A_Fall (mobj_t *actor);
  66. //
  67. // ENEMY THINKING
  68. // Enemies are allways spawned
  69. // with targetplayer = -1, threshold = 0
  70. // Most monsters are spawned unaware of all players,
  71. // but some can be made preaware
  72. //
  73. //
  74. // Called by P_NoiseAlert.
  75. // Recursively traverse adjacent sectors,
  76. // sound blocking lines cut off traversal.
  77. //
  78. mobj_t* soundtarget;
  79. void
  80. P_RecursiveSound
  81. ( sector_t* sec,
  82.   int soundblocks )
  83. {
  84.     int i;
  85.     line_t* check;
  86.     sector_t* other;
  87.     // wake up all monsters in this sector
  88.     if (sec->validcount == validcount
  89. && sec->soundtraversed <= soundblocks+1)
  90.     {
  91. return; // already flooded
  92.     }
  93.     
  94.     sec->validcount = validcount;
  95.     sec->soundtraversed = soundblocks+1;
  96.     sec->soundtarget = soundtarget;
  97.     for (i=0 ;i<sec->linecount ; i++)
  98.     {
  99. check = sec->lines[i];
  100. if (! (check->flags & ML_TWOSIDED) )
  101.     continue;
  102. P_LineOpening (check);
  103. if (openrange <= 0)
  104.     continue; // closed door
  105. if ( sides[ check->sidenum[0] ].sector == sec)
  106.     other = sides[ check->sidenum[1] ] .sector;
  107. else
  108.     other = sides[ check->sidenum[0] ].sector;
  109. if (check->flags & ML_SOUNDBLOCK)
  110. {
  111.     if (!soundblocks)
  112. P_RecursiveSound (other, 1);
  113. }
  114. else
  115.     P_RecursiveSound (other, soundblocks);
  116.     }
  117. }
  118. //
  119. // P_NoiseAlert
  120. // If a monster yells at a player,
  121. // it will alert other monsters to the player.
  122. //
  123. void
  124. P_NoiseAlert
  125. ( mobj_t* target,
  126.   mobj_t* emmiter )
  127. {
  128.     soundtarget = target;
  129.     validcount++;
  130.     P_RecursiveSound (emmiter->subsector->sector, 0);
  131. }
  132. //
  133. // P_CheckMeleeRange
  134. //
  135. boolean P_CheckMeleeRange (mobj_t* actor)
  136. {
  137.     mobj_t* pl;
  138.     fixed_t dist;
  139.     if (!actor->target)
  140. return false;
  141.     pl = actor->target;
  142.     dist = P_AproxDistance (pl->x-actor->x, pl->y-actor->y);
  143.     if (dist >= MELEERANGE-20*FRACUNIT+pl->info->radius)
  144. return false;
  145.     if (! P_CheckSight (actor, actor->target) )
  146. return false;
  147.     return true;
  148. }
  149. //
  150. // P_CheckMissileRange
  151. //
  152. boolean P_CheckMissileRange (mobj_t* actor)
  153. {
  154.     fixed_t dist;
  155.     if (! P_CheckSight (actor, actor->target) )
  156. return false;
  157.     if ( actor->flags & MF_JUSTHIT )
  158.     {
  159. // the target just hit the enemy,
  160. // so fight back!
  161. actor->flags &= ~MF_JUSTHIT;
  162. return true;
  163.     }
  164.     if (actor->reactiontime)
  165. return false; // do not attack yet
  166.     // OPTIMIZE: get this from a global checksight
  167.     dist = P_AproxDistance ( actor->x-actor->target->x,
  168.      actor->y-actor->target->y) - 64*FRACUNIT;
  169.     
  170.     if (!actor->info->meleestate)
  171. dist -= 128*FRACUNIT; // no melee attack, so fire more
  172.     dist >>= 16;
  173.     if (actor->type == MT_VILE)
  174.     {
  175. if (dist > 14*64)
  176.     return false; // too far away
  177.     }
  178.     if (actor->type == MT_UNDEAD)
  179.     {
  180. if (dist < 196)
  181.     return false; // close for fist attack
  182. dist >>= 1;
  183.     }
  184.     if (actor->type == MT_CYBORG
  185. || actor->type == MT_SPIDER
  186. || actor->type == MT_SKULL)
  187.     {
  188. dist >>= 1;
  189.     }
  190.     
  191.     if (dist > 200)
  192. dist = 200;
  193.     if (actor->type == MT_CYBORG && dist > 160)
  194. dist = 160;
  195.     if (P_Random () < dist)
  196. return false;
  197.     return true;
  198. }
  199. //
  200. // P_Move
  201. // Move in the current direction,
  202. // returns false if the move is blocked.
  203. //
  204. fixed_t xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000};
  205. fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000};
  206. #define MAXSPECIALCROSS 8
  207. extern line_t* spechit[MAXSPECIALCROSS];
  208. extern int numspechit;
  209. boolean P_Move (mobj_t* actor)
  210. {
  211.     fixed_t tryx;
  212.     fixed_t tryy;
  213.     
  214.     line_t* ld;
  215.     
  216.     // warning: 'catch', 'throw', and 'try'
  217.     // are all C++ reserved words
  218.     boolean try_ok;
  219.     boolean good;
  220.     if (actor->movedir == DI_NODIR)
  221. return false;
  222.     if ((unsigned)actor->movedir >= 8)
  223. I_Error ("Weird actor->movedir!");
  224.     tryx = actor->x + actor->info->speed*xspeed[actor->movedir];
  225.     tryy = actor->y + actor->info->speed*yspeed[actor->movedir];
  226.     try_ok = P_TryMove (actor, tryx, tryy);
  227.     if (!try_ok)
  228.     {
  229. // open any specials
  230. if (actor->flags & MF_FLOAT && floatok)
  231. {
  232.     // must adjust height
  233.     if (actor->z < tmfloorz)
  234. actor->z += FLOATSPEED;
  235.     else
  236. actor->z -= FLOATSPEED;
  237.     actor->flags |= MF_INFLOAT;
  238.     return true;
  239. }
  240. if (!numspechit)
  241.     return false;
  242. actor->movedir = DI_NODIR;
  243. good = false;
  244. while (numspechit--)
  245. {
  246.     ld = spechit[numspechit];
  247.     // if the special is not a door
  248.     // that can be opened,
  249.     // return false
  250.     if (P_UseSpecialLine (actor, ld,0))
  251. good = true;
  252. }
  253. return good;
  254.     }
  255.     else
  256.     {
  257. actor->flags &= ~MF_INFLOAT;
  258.     }
  259.     if (! (actor->flags & MF_FLOAT) )
  260. actor->z = actor->floorz;
  261.     return true; 
  262. }
  263. //
  264. // TryWalk
  265. // Attempts to move actor on
  266. // in its current (ob->moveangle) direction.
  267. // If blocked by either a wall or an actor
  268. // returns FALSE
  269. // If move is either clear or blocked only by a door,
  270. // returns TRUE and sets...
  271. // If a door is in the way,
  272. // an OpenDoor call is made to start it opening.
  273. //
  274. boolean P_TryWalk (mobj_t* actor)
  275. {
  276.     if (!P_Move (actor))
  277.     {
  278. return false;
  279.     }
  280.     actor->movecount = P_Random()&15;
  281.     return true;
  282. }
  283. void P_NewChaseDir (mobj_t* actor)
  284. {
  285.     fixed_t deltax;
  286.     fixed_t deltay;
  287.     
  288.     dirtype_t d[3];
  289.     
  290.     int tdir;
  291.     dirtype_t olddir;
  292.     
  293.     dirtype_t turnaround;
  294.     if (!actor->target)
  295. I_Error ("P_NewChaseDir: called with no target");
  296.     olddir = actor->movedir;
  297.     turnaround=opposite[olddir];
  298.     deltax = actor->target->x - actor->x;
  299.     deltay = actor->target->y - actor->y;
  300.     if (deltax>10*FRACUNIT)
  301. d[1]= DI_EAST;
  302.     else if (deltax<-10*FRACUNIT)
  303. d[1]= DI_WEST;
  304.     else
  305. d[1]=DI_NODIR;
  306.     if (deltay<-10*FRACUNIT)
  307. d[2]= DI_SOUTH;
  308.     else if (deltay>10*FRACUNIT)
  309. d[2]= DI_NORTH;
  310.     else
  311. d[2]=DI_NODIR;
  312.     // try direct route
  313.     if (d[1] != DI_NODIR
  314. && d[2] != DI_NODIR)
  315.     {
  316. actor->movedir = diags[((deltay<0)<<1)+(deltax>0)];
  317. if (actor->movedir != turnaround && P_TryWalk(actor))
  318.     return;
  319.     }
  320.     // try other directions
  321.     if (P_Random() > 200
  322. ||  abs(deltay)>abs(deltax))
  323.     {
  324. tdir=d[1];
  325. d[1]=d[2];
  326. d[2]=tdir;
  327.     }
  328.     if (d[1]==turnaround)
  329. d[1]=DI_NODIR;
  330.     if (d[2]==turnaround)
  331. d[2]=DI_NODIR;
  332.     if (d[1]!=DI_NODIR)
  333.     {
  334. actor->movedir = d[1];
  335. if (P_TryWalk(actor))
  336. {
  337.     // either moved forward or attacked
  338.     return;
  339. }
  340.     }
  341.     if (d[2]!=DI_NODIR)
  342.     {
  343. actor->movedir =d[2];
  344. if (P_TryWalk(actor))
  345.     return;
  346.     }
  347.     // there is no direct path to the player,
  348.     // so pick another direction.
  349.     if (olddir!=DI_NODIR)
  350.     {
  351. actor->movedir =olddir;
  352. if (P_TryWalk(actor))
  353.     return;
  354.     }
  355.     // randomly determine direction of search
  356.     if (P_Random()&1) 
  357.     {
  358. for ( tdir=DI_EAST;
  359.       tdir<=DI_SOUTHEAST;
  360.       tdir++ )
  361. {
  362.     if (tdir!=turnaround)
  363.     {
  364. actor->movedir =tdir;
  365. if ( P_TryWalk(actor) )
  366.     return;
  367.     }
  368. }
  369.     }
  370.     else
  371.     {
  372. for ( tdir=DI_SOUTHEAST;
  373.       tdir != (DI_EAST-1);
  374.       tdir-- )
  375. {
  376.     if (tdir!=turnaround)
  377.     {
  378. actor->movedir =tdir;
  379. if ( P_TryWalk(actor) )
  380.     return;
  381.     }
  382. }
  383.     }
  384.     if (turnaround !=  DI_NODIR)
  385.     {
  386. actor->movedir =turnaround;
  387. if ( P_TryWalk(actor) )
  388.     return;
  389.     }
  390.     actor->movedir = DI_NODIR; // can not move
  391. }
  392. //
  393. // P_LookForPlayers
  394. // If allaround is false, only look 180 degrees in front.
  395. // Returns true if a player is targeted.
  396. //
  397. boolean
  398. P_LookForPlayers
  399. ( mobj_t* actor,
  400.   boolean allaround )
  401. {
  402.     int c;
  403.     int stop;
  404.     player_t* player;
  405.     sector_t* sector;
  406.     angle_t an;
  407.     fixed_t dist;
  408.     sector = actor->subsector->sector;
  409.     c = 0;
  410.     stop = (actor->lastlook-1)&3;
  411.     for ( ; ; actor->lastlook = (actor->lastlook+1)&3 )
  412.     {
  413. if (!playeringame[actor->lastlook])
  414.     continue;
  415. if (c++ == 2
  416.     || actor->lastlook == stop)
  417. {
  418.     // done looking
  419.     return false;
  420. }
  421. player = &players[actor->lastlook];
  422. if (player->health <= 0)
  423.     continue; // dead
  424. if (!P_CheckSight (actor, player->mo))
  425.     continue; // out of sight
  426. if (!allaround)
  427. {
  428.     an = R_PointToAngle2 (actor->x,
  429.   actor->y, 
  430.   player->mo->x,
  431.   player->mo->y)
  432. - actor->angle;
  433.     
  434.     if (an > ANG90 && an < ANG270)
  435.     {
  436. dist = P_AproxDistance (player->mo->x - actor->x,
  437. player->mo->y - actor->y);
  438. // if real close, react anyway
  439. if (dist > MELEERANGE)
  440.     continue; // behind back
  441.     }
  442. }
  443. actor->target = player->mo;
  444. return true;
  445.     }
  446.     return false;
  447. }
  448. //
  449. // A_KeenDie
  450. // DOOM II special, map 32.
  451. // Uses special tag 666.
  452. //
  453. void A_KeenDie (mobj_t* mo)
  454. {
  455.     thinker_t* th;
  456.     mobj_t* mo2;
  457.     line_t junk;
  458.     A_Fall (mo);
  459.     
  460.     // scan the remaining thinkers
  461.     // to see if all Keens are dead
  462.     for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
  463.     {
  464. if (th->function.acp1 != (actionf_p1)P_MobjThinker)
  465.     continue;
  466. mo2 = (mobj_t *)th;
  467. if (mo2 != mo
  468.     && mo2->type == mo->type
  469.     && mo2->health > 0)
  470. {
  471.     // other Keen not dead
  472.     return;
  473. }
  474.     }
  475.     junk.tag = 666;
  476.     EV_DoDoor(&junk,open);
  477. }
  478. //
  479. // ACTION ROUTINES
  480. //
  481. //
  482. // A_Look
  483. // Stay in state until a player is sighted.
  484. //
  485. void A_Look (mobj_t* actor)
  486. {
  487.     mobj_t* targ;
  488.     actor->threshold = 0; // any shot will wake up
  489.     targ = actor->subsector->sector->soundtarget;
  490.     if (targ
  491. && (targ->flags & MF_SHOOTABLE) )
  492.     {
  493. actor->target = targ;
  494. if ( actor->flags & MF_AMBUSH )
  495. {
  496.     if (P_CheckSight (actor, actor->target))
  497. goto seeyou;
  498. }
  499. else
  500.     goto seeyou;
  501.     }
  502.     if (!P_LookForPlayers (actor, false) )
  503. return;
  504.     // go into chase state
  505.   seeyou:
  506.     if (actor->info->seesound)
  507.     {
  508. int sound;
  509. switch (actor->info->seesound)
  510. {
  511.   case sfx_posit1:
  512.   case sfx_posit2:
  513.   case sfx_posit3:
  514.     sound = sfx_posit1+P_Random()%3;
  515.     break;
  516.   case sfx_bgsit1:
  517.   case sfx_bgsit2:
  518.     sound = sfx_bgsit1+P_Random()%2;
  519.     break;
  520.   default:
  521.     sound = actor->info->seesound;
  522.     break;
  523. }
  524. if (actor->type==MT_SPIDER
  525.     || actor->type == MT_CYBORG)
  526. {
  527.     // full volume
  528.     S_StartSound (NULL, sound);
  529. }
  530. else
  531.     S_StartSound (actor, sound);
  532.     }
  533.     P_SetMobjState (actor, actor->info->seestate);
  534. }
  535. //
  536. // A_Chase
  537. // Actor has a melee attack,
  538. // so it tries to close as fast as possible
  539. //
  540. void A_Chase (mobj_t* actor)
  541. {
  542.     int delta;
  543.     if (actor->reactiontime)
  544. actor->reactiontime--;
  545.     // modify target threshold
  546.     if  (actor->threshold)
  547.     {
  548. if (!actor->target
  549.     || actor->target->health <= 0)
  550. {
  551.     actor->threshold = 0;
  552. }
  553. else
  554.     actor->threshold--;
  555.     }
  556.     
  557.     // turn towards movement direction if not there yet
  558.     if (actor->movedir < 8)
  559.     {
  560. actor->angle &= (7<<29);
  561. delta = actor->angle - (actor->movedir << 29);
  562. if (delta > 0)
  563.     actor->angle -= ANG90/2;
  564. else if (delta < 0)
  565.     actor->angle += ANG90/2;
  566.     }
  567.     if (!actor->target
  568. || !(actor->target->flags&MF_SHOOTABLE))
  569.     {
  570. // look for a new target
  571. if (P_LookForPlayers(actor,true))
  572.     return;  // got a new target
  573. P_SetMobjState (actor, actor->info->spawnstate);
  574. return;
  575.     }
  576.     
  577.     // do not attack twice in a row
  578.     if (actor->flags & MF_JUSTATTACKED)
  579.     {
  580. actor->flags &= ~MF_JUSTATTACKED;
  581. if (gameskill != sk_nightmare && !fastparm)
  582.     P_NewChaseDir (actor);
  583. return;
  584.     }
  585.     
  586.     // check for melee attack
  587.     if (actor->info->meleestate
  588. && P_CheckMeleeRange (actor))
  589.     {
  590. if (actor->info->attacksound)
  591.     S_StartSound (actor, actor->info->attacksound);
  592. P_SetMobjState (actor, actor->info->meleestate);
  593. return;
  594.     }
  595.     
  596.     // check for missile attack
  597.     if (actor->info->missilestate)
  598.     {
  599. if (gameskill < sk_nightmare
  600.     && !fastparm && actor->movecount)
  601. {
  602.     goto nomissile;
  603. }
  604. if (!P_CheckMissileRange (actor))
  605.     goto nomissile;
  606. P_SetMobjState (actor, actor->info->missilestate);
  607. actor->flags |= MF_JUSTATTACKED;
  608. return;
  609.     }
  610.     // ?
  611.   nomissile:
  612.     // possibly choose another target
  613.     if (netgame
  614. && !actor->threshold
  615. && !P_CheckSight (actor, actor->target) )
  616.     {
  617. if (P_LookForPlayers(actor,true))
  618.     return; // got a new target
  619.     }
  620.     
  621.     // chase towards player
  622.     if (--actor->movecount<0
  623. || !P_Move (actor))
  624.     {
  625. P_NewChaseDir (actor);
  626.     }
  627.     
  628.     // make active sound
  629.     if (actor->info->activesound
  630. && P_Random () < 3)
  631.     {
  632. S_StartSound (actor, actor->info->activesound);
  633.     }
  634. }
  635. //
  636. // A_FaceTarget
  637. //
  638. void A_FaceTarget (mobj_t* actor)
  639. {
  640.     if (!actor->target)
  641. return;
  642.     
  643.     actor->flags &= ~MF_AMBUSH;
  644.     actor->angle = R_PointToAngle2 (actor->x,
  645.     actor->y,
  646.     actor->target->x,
  647.     actor->target->y);
  648.     
  649.     if (actor->target->flags & MF_SHADOW)
  650. actor->angle += (P_Random()-P_Random())<<21;
  651. }
  652. //
  653. // A_PosAttack
  654. //
  655. void A_PosAttack (mobj_t* actor)
  656. {
  657.     int angle;
  658.     int damage;
  659.     int slope;
  660.     if (!actor->target)
  661. return;
  662.     A_FaceTarget (actor);
  663.     angle = actor->angle;
  664.     slope = P_AimLineAttack (actor, angle, MISSILERANGE);
  665.     S_StartSound (actor, sfx_pistol);
  666.     angle += (P_Random()-P_Random())<<20;
  667.     damage = ((P_Random()%5)+1)*3;
  668.     P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
  669. }
  670. void A_SPosAttack (mobj_t* actor)
  671. {
  672.     int i;
  673.     int angle;
  674.     int bangle;
  675.     int damage;
  676.     int slope;
  677.     if (!actor->target)
  678. return;
  679.     S_StartSound (actor, sfx_shotgn);
  680.     A_FaceTarget (actor);
  681.     bangle = actor->angle;
  682.     slope = P_AimLineAttack (actor, bangle, MISSILERANGE);
  683.     for (i=0 ; i<3 ; i++)
  684.     {
  685. angle = bangle + ((P_Random()-P_Random())<<20);
  686. damage = ((P_Random()%5)+1)*3;
  687. P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
  688.     }
  689. }
  690. void A_CPosAttack (mobj_t* actor)
  691. {
  692.     int angle;
  693.     int bangle;
  694.     int damage;
  695.     int slope;
  696.     if (!actor->target)
  697. return;
  698.     S_StartSound (actor, sfx_shotgn);
  699.     A_FaceTarget (actor);
  700.     bangle = actor->angle;
  701.     slope = P_AimLineAttack (actor, bangle, MISSILERANGE);
  702.     angle = bangle + ((P_Random()-P_Random())<<20);
  703.     damage = ((P_Random()%5)+1)*3;
  704.     P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
  705. }
  706. void A_CPosRefire (mobj_t* actor)
  707. {
  708.     // keep firing unless target got out of sight
  709.     A_FaceTarget (actor);
  710.     if (P_Random () < 40)
  711. return;
  712.     if (!actor->target
  713. || actor->target->health <= 0
  714. || !P_CheckSight (actor, actor->target) )
  715.     {
  716. P_SetMobjState (actor, actor->info->seestate);
  717.     }
  718. }
  719. void A_SpidRefire (mobj_t* actor)
  720. {
  721.     // keep firing unless target got out of sight
  722.     A_FaceTarget (actor);
  723.     if (P_Random () < 10)
  724. return;
  725.     if (!actor->target
  726. || actor->target->health <= 0
  727. || !P_CheckSight (actor, actor->target) )
  728.     {
  729. P_SetMobjState (actor, actor->info->seestate);
  730.     }
  731. }
  732. void A_BspiAttack (mobj_t *actor)
  733. {
  734.     if (!actor->target)
  735. return;
  736.     A_FaceTarget (actor);
  737.     // launch a missile
  738.     P_SpawnMissile (actor, actor->target, MT_ARACHPLAZ);
  739. }
  740. //
  741. // A_TroopAttack
  742. //
  743. void A_TroopAttack (mobj_t* actor)
  744. {
  745.     int damage;
  746.     if (!actor->target)
  747. return;
  748.     A_FaceTarget (actor);
  749.     if (P_CheckMeleeRange (actor))
  750.     {
  751. S_StartSound (actor, sfx_claw);
  752. damage = (P_Random()%8+1)*3;
  753. P_DamageMobj (actor->target, actor, actor, damage);
  754. return;
  755.     }
  756.     
  757.     // launch a missile
  758.     P_SpawnMissile (actor, actor->target, MT_TROOPSHOT);
  759. }
  760. void A_SargAttack (mobj_t* actor)
  761. {
  762.     int damage;
  763.     if (!actor->target)
  764. return;
  765.     A_FaceTarget (actor);
  766.     if (P_CheckMeleeRange (actor))
  767.     {
  768. damage = ((P_Random()%10)+1)*4;
  769. P_DamageMobj (actor->target, actor, actor, damage);
  770.     }
  771. }
  772. void A_HeadAttack (mobj_t* actor)
  773. {
  774.     int damage;
  775.     if (!actor->target)
  776. return;
  777.     A_FaceTarget (actor);
  778.     if (P_CheckMeleeRange (actor))
  779.     {
  780. damage = (P_Random()%6+1)*10;
  781. P_DamageMobj (actor->target, actor, actor, damage);
  782. return;
  783.     }
  784.     
  785.     // launch a missile
  786.     P_SpawnMissile (actor, actor->target, MT_HEADSHOT);
  787. }
  788. void A_CyberAttack (mobj_t* actor)
  789. {
  790.     if (!actor->target)
  791. return;
  792.     A_FaceTarget (actor);
  793.     P_SpawnMissile (actor, actor->target, MT_ROCKET);
  794. }
  795. void A_BruisAttack (mobj_t* actor)
  796. {
  797.     int damage;
  798.     if (!actor->target)
  799. return;
  800.     if (P_CheckMeleeRange (actor))
  801.     {
  802. S_StartSound (actor, sfx_claw);
  803. damage = (P_Random()%8+1)*10;
  804. P_DamageMobj (actor->target, actor, actor, damage);
  805. return;
  806.     }
  807.     
  808.     // launch a missile
  809.     P_SpawnMissile (actor, actor->target, MT_BRUISERSHOT);
  810. }
  811. //
  812. // A_SkelMissile
  813. //
  814. void A_SkelMissile (mobj_t* actor)
  815. {
  816.     mobj_t* mo;
  817.     if (!actor->target)
  818. return;
  819.     A_FaceTarget (actor);
  820.     actor->z += 16*FRACUNIT; // so missile spawns higher
  821.     mo = P_SpawnMissile (actor, actor->target, MT_TRACER);
  822.     actor->z -= 16*FRACUNIT; // back to normal
  823.     mo->x += mo->momx;
  824.     mo->y += mo->momy;
  825.     mo->tracer = actor->target;
  826. }
  827. int TRACEANGLE = 0xc000000;
  828. void A_Tracer (mobj_t* actor)
  829. {
  830.     angle_t exact;
  831.     fixed_t dist;
  832.     fixed_t slope;
  833.     mobj_t* dest;
  834.     mobj_t* th;
  835.     if (gametic & 3)
  836. return;
  837.     
  838.     // spawn a puff of smoke behind the rocket
  839.     P_SpawnPuff (actor->x, actor->y, actor->z);
  840.     th = P_SpawnMobj (actor->x-actor->momx,
  841.       actor->y-actor->momy,
  842.       actor->z, MT_SMOKE);
  843.     
  844.     th->momz = FRACUNIT;
  845.     th->tics -= P_Random()&3;
  846.     if (th->tics < 1)
  847. th->tics = 1;
  848.     
  849.     // adjust direction
  850.     dest = actor->tracer;
  851.     if (!dest || dest->health <= 0)
  852. return;
  853.     
  854.     // change angle
  855.     exact = R_PointToAngle2 (actor->x,
  856.      actor->y,
  857.      dest->x,
  858.      dest->y);
  859.     if (exact != actor->angle)
  860.     {
  861. if (exact - actor->angle > 0x80000000)
  862. {
  863.     actor->angle -= TRACEANGLE;
  864.     if (exact - actor->angle < 0x80000000)
  865. actor->angle = exact;
  866. }
  867. else
  868. {
  869.     actor->angle += TRACEANGLE;
  870.     if (exact - actor->angle > 0x80000000)
  871. actor->angle = exact;
  872. }
  873.     }
  874.     exact = actor->angle>>ANGLETOFINESHIFT;
  875.     actor->momx = FixedMul (actor->info->speed, finecosine[exact]);
  876.     actor->momy = FixedMul (actor->info->speed, finesine[exact]);
  877.     
  878.     // change slope
  879.     dist = P_AproxDistance (dest->x - actor->x,
  880.     dest->y - actor->y);
  881.     
  882.     dist = dist / actor->info->speed;
  883.     if (dist < 1)
  884. dist = 1;
  885.     slope = (dest->z+40*FRACUNIT - actor->z) / dist;
  886.     if (slope < actor->momz)
  887. actor->momz -= FRACUNIT/8;
  888.     else
  889. actor->momz += FRACUNIT/8;
  890. }
  891. void A_SkelWhoosh (mobj_t* actor)
  892. {
  893.     if (!actor->target)
  894. return;
  895.     A_FaceTarget (actor);
  896.     S_StartSound (actor,sfx_skeswg);
  897. }
  898. void A_SkelFist (mobj_t* actor)
  899. {
  900.     int damage;
  901.     if (!actor->target)
  902. return;
  903.     A_FaceTarget (actor);
  904.     if (P_CheckMeleeRange (actor))
  905.     {
  906. damage = ((P_Random()%10)+1)*6;
  907. S_StartSound (actor, sfx_skepch);
  908. P_DamageMobj (actor->target, actor, actor, damage);
  909.     }
  910. }
  911. //
  912. // PIT_VileCheck
  913. // Detect a corpse that could be raised.
  914. //
  915. mobj_t* corpsehit;
  916. mobj_t* vileobj;
  917. fixed_t viletryx;
  918. fixed_t viletryy;
  919. boolean PIT_VileCheck (mobj_t* thing)
  920. {
  921.     int maxdist;
  922.     boolean check;
  923.     if (!(thing->flags & MF_CORPSE) )
  924. return true; // not a monster
  925.     
  926.     if (thing->tics != -1)
  927. return true; // not lying still yet
  928.     
  929.     if (thing->info->raisestate == S_NULL)
  930. return true; // monster doesn't have a raise state
  931.     
  932.     maxdist = thing->info->radius + mobjinfo[MT_VILE].radius;
  933.     if ( abs(thing->x - viletryx) > maxdist
  934.  || abs(thing->y - viletryy) > maxdist )
  935. return true; // not actually touching
  936.     corpsehit = thing;
  937.     corpsehit->momx = corpsehit->momy = 0;
  938.     corpsehit->height <<= 2;
  939.     check = P_CheckPosition (corpsehit, corpsehit->x, corpsehit->y);
  940.     corpsehit->height >>= 2;
  941.     if (!check)
  942. return true; // doesn't fit here
  943.     return false; // got one, so stop checking
  944. }
  945. //
  946. // A_VileChase
  947. // Check for ressurecting a body
  948. //
  949. void A_VileChase (mobj_t* actor)
  950. {
  951.     int xl;
  952.     int xh;
  953.     int yl;
  954.     int yh;
  955.     
  956.     int bx;
  957.     int by;
  958.     mobjinfo_t* info;
  959.     mobj_t* temp;
  960.     if (actor->movedir != DI_NODIR)
  961.     {
  962. // check for corpses to raise
  963. viletryx =
  964.     actor->x + actor->info->speed*xspeed[actor->movedir];
  965. viletryy =
  966.     actor->y + actor->info->speed*yspeed[actor->movedir];
  967. xl = (viletryx - bmaporgx - MAXRADIUS*2)>>MAPBLOCKSHIFT;
  968. xh = (viletryx - bmaporgx + MAXRADIUS*2)>>MAPBLOCKSHIFT;
  969. yl = (viletryy - bmaporgy - MAXRADIUS*2)>>MAPBLOCKSHIFT;
  970. yh = (viletryy - bmaporgy + MAXRADIUS*2)>>MAPBLOCKSHIFT;
  971. vileobj = actor;
  972. for (bx=xl ; bx<=xh ; bx++)
  973. {
  974.     for (by=yl ; by<=yh ; by++)
  975.     {
  976. // Call PIT_VileCheck to check
  977. // whether object is a corpse
  978. // that canbe raised.
  979. if (!P_BlockThingsIterator(bx,by,PIT_VileCheck))
  980. {
  981.     // got one!
  982.     temp = actor->target;
  983.     actor->target = corpsehit;
  984.     A_FaceTarget (actor);
  985.     actor->target = temp;
  986.     P_SetMobjState (actor, S_VILE_HEAL1);
  987.     S_StartSound (corpsehit, sfx_slop);
  988.     info = corpsehit->info;
  989.     
  990.     P_SetMobjState (corpsehit,info->raisestate);
  991.     corpsehit->height <<= 2;
  992.     corpsehit->flags = info->flags;
  993.     corpsehit->health = info->spawnhealth;
  994.     corpsehit->target = NULL;
  995.     return;
  996. }
  997.     }
  998. }
  999.     }
  1000.     // Return to normal attack.
  1001.     A_Chase (actor);
  1002. }
  1003. //
  1004. // A_VileStart
  1005. //
  1006. void A_VileStart (mobj_t* actor)
  1007. {
  1008.     S_StartSound (actor, sfx_vilatk);
  1009. }
  1010. //
  1011. // A_Fire
  1012. // Keep fire in front of player unless out of sight
  1013. //
  1014. void A_Fire (mobj_t* actor);
  1015. void A_StartFire (mobj_t* actor)
  1016. {
  1017.     S_StartSound(actor,sfx_flamst);
  1018.     A_Fire(actor);
  1019. }
  1020. void A_FireCrackle (mobj_t* actor)
  1021. {
  1022.     S_StartSound(actor,sfx_flame);
  1023.     A_Fire(actor);
  1024. }
  1025. void A_Fire (mobj_t* actor)
  1026. {
  1027.     mobj_t* dest;
  1028.     unsigned an;
  1029.     dest = actor->tracer;
  1030.     if (!dest)
  1031. return;
  1032.     // don't move it if the vile lost sight
  1033.     if (!P_CheckSight (actor->target, dest) )
  1034. return;
  1035.     an = dest->angle >> ANGLETOFINESHIFT;
  1036.     P_UnsetThingPosition (actor);
  1037.     actor->x = dest->x + FixedMul (24*FRACUNIT, finecosine[an]);
  1038.     actor->y = dest->y + FixedMul (24*FRACUNIT, finesine[an]);
  1039.     actor->z = dest->z;
  1040.     P_SetThingPosition (actor);
  1041. }
  1042. //
  1043. // A_VileTarget
  1044. // Spawn the hellfire
  1045. //
  1046. void A_VileTarget (mobj_t* actor)
  1047. {
  1048.     mobj_t* fog;
  1049.     if (!actor->target)
  1050. return;
  1051.     A_FaceTarget (actor);
  1052.     fog = P_SpawnMobj (actor->target->x,
  1053.        actor->target->x,
  1054.        actor->target->z, MT_FIRE);
  1055.     
  1056.     actor->tracer = fog;
  1057.     fog->target = actor;
  1058.     fog->tracer = actor->target;
  1059.     A_Fire (fog);
  1060. }
  1061. //
  1062. // A_VileAttack
  1063. //
  1064. void A_VileAttack (mobj_t* actor)
  1065. {
  1066.     mobj_t* fire;
  1067.     int an;
  1068.     if (!actor->target)
  1069. return;
  1070.     
  1071.     A_FaceTarget (actor);
  1072.     if (!P_CheckSight (actor, actor->target) )
  1073. return;
  1074.     S_StartSound (actor, sfx_barexp);
  1075.     P_DamageMobj (actor->target, actor, actor, 20);
  1076.     actor->target->momz = 1000*FRACUNIT/actor->target->info->mass;
  1077.     an = actor->angle >> ANGLETOFINESHIFT;
  1078.     fire = actor->tracer;
  1079.     if (!fire)
  1080. return;
  1081.     // move the fire between the vile and the player
  1082.     fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]);
  1083.     fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]);
  1084.     P_RadiusAttack (fire, actor, 70 );
  1085. }
  1086. //
  1087. // Mancubus attack,
  1088. // firing three missiles (bruisers)
  1089. // in three different directions?
  1090. // Doesn't look like it. 
  1091. //
  1092. #define FATSPREAD (ANG90/8)
  1093. void A_FatRaise (mobj_t *actor)
  1094. {
  1095.     A_FaceTarget (actor);
  1096.     S_StartSound (actor, sfx_manatk);
  1097. }
  1098. void A_FatAttack1 (mobj_t* actor)
  1099. {
  1100.     mobj_t* mo;
  1101.     int an;
  1102.     A_FaceTarget (actor);
  1103.     // Change direction  to ...
  1104.     actor->angle += FATSPREAD;
  1105.     P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1106.     mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1107.     mo->angle += FATSPREAD;
  1108.     an = mo->angle >> ANGLETOFINESHIFT;
  1109.     mo->momx = FixedMul (mo->info->speed, finecosine[an]);
  1110.     mo->momy = FixedMul (mo->info->speed, finesine[an]);
  1111. }
  1112. void A_FatAttack2 (mobj_t* actor)
  1113. {
  1114.     mobj_t* mo;
  1115.     int an;
  1116.     A_FaceTarget (actor);
  1117.     // Now here choose opposite deviation.
  1118.     actor->angle -= FATSPREAD;
  1119.     P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1120.     mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1121.     mo->angle -= FATSPREAD*2;
  1122.     an = mo->angle >> ANGLETOFINESHIFT;
  1123.     mo->momx = FixedMul (mo->info->speed, finecosine[an]);
  1124.     mo->momy = FixedMul (mo->info->speed, finesine[an]);
  1125. }
  1126. void A_FatAttack3 (mobj_t* actor)
  1127. {
  1128.     mobj_t* mo;
  1129.     int an;
  1130.     A_FaceTarget (actor);
  1131.     
  1132.     mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1133.     mo->angle -= FATSPREAD/2;
  1134.     an = mo->angle >> ANGLETOFINESHIFT;
  1135.     mo->momx = FixedMul (mo->info->speed, finecosine[an]);
  1136.     mo->momy = FixedMul (mo->info->speed, finesine[an]);
  1137.     mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1138.     mo->angle += FATSPREAD/2;
  1139.     an = mo->angle >> ANGLETOFINESHIFT;
  1140.     mo->momx = FixedMul (mo->info->speed, finecosine[an]);
  1141.     mo->momy = FixedMul (mo->info->speed, finesine[an]);
  1142. }
  1143. //
  1144. // SkullAttack
  1145. // Fly at the player like a missile.
  1146. //
  1147. #define SKULLSPEED (20*FRACUNIT)
  1148. void A_SkullAttack (mobj_t* actor)
  1149. {
  1150.     mobj_t* dest;
  1151.     angle_t an;
  1152.     int dist;
  1153.     if (!actor->target)
  1154. return;
  1155.     dest = actor->target;
  1156.     actor->flags |= MF_SKULLFLY;
  1157.     S_StartSound (actor, actor->info->attacksound);
  1158.     A_FaceTarget (actor);
  1159.     an = actor->angle >> ANGLETOFINESHIFT;
  1160.     actor->momx = FixedMul (SKULLSPEED, finecosine[an]);
  1161.     actor->momy = FixedMul (SKULLSPEED, finesine[an]);
  1162.     dist = P_AproxDistance (dest->x - actor->x, dest->y - actor->y);
  1163.     dist = dist / SKULLSPEED;
  1164.     
  1165.     if (dist < 1)
  1166. dist = 1;
  1167.     actor->momz = (dest->z+(dest->height>>1) - actor->z) / dist;
  1168. }
  1169. //
  1170. // A_PainShootSkull
  1171. // Spawn a lost soul and launch it at the target
  1172. //
  1173. void
  1174. A_PainShootSkull
  1175. ( mobj_t* actor,
  1176.   angle_t angle )
  1177. {
  1178.     fixed_t x;
  1179.     fixed_t y;
  1180.     fixed_t z;
  1181.     
  1182.     mobj_t* newmobj;
  1183.     angle_t an;
  1184.     int prestep;
  1185.     int count;
  1186.     thinker_t* currentthinker;
  1187.     // count total number of skull currently on the level
  1188.     count = 0;
  1189.     currentthinker = thinkercap.next;
  1190.     while (currentthinker != &thinkercap)
  1191.     {
  1192. if (   (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
  1193.     && ((mobj_t *)currentthinker)->type == MT_SKULL)
  1194.     count++;
  1195. currentthinker = currentthinker->next;
  1196.     }
  1197.     // if there are allready 20 skulls on the level,
  1198.     // don't spit another one
  1199.     if (count > 20)
  1200. return;
  1201.     // okay, there's playe for another one
  1202.     an = angle >> ANGLETOFINESHIFT;
  1203.     
  1204.     prestep =
  1205. 4*FRACUNIT
  1206. + 3*(actor->info->radius + mobjinfo[MT_SKULL].radius)/2;
  1207.     
  1208.     x = actor->x + FixedMul (prestep, finecosine[an]);
  1209.     y = actor->y + FixedMul (prestep, finesine[an]);
  1210.     z = actor->z + 8*FRACUNIT;
  1211.     newmobj = P_SpawnMobj (x , y, z, MT_SKULL);
  1212.     // Check for movements.
  1213.     if (!P_TryMove (newmobj, newmobj->x, newmobj->y))
  1214.     {
  1215. // kill it immediately
  1216. P_DamageMobj (newmobj,actor,actor,10000);
  1217. return;
  1218.     }
  1219.     newmobj->target = actor->target;
  1220.     A_SkullAttack (newmobj);
  1221. }
  1222. //
  1223. // A_PainAttack
  1224. // Spawn a lost soul and launch it at the target
  1225. // 
  1226. void A_PainAttack (mobj_t* actor)
  1227. {
  1228.     if (!actor->target)
  1229. return;
  1230.     A_FaceTarget (actor);
  1231.     A_PainShootSkull (actor, actor->angle);
  1232. }
  1233. void A_PainDie (mobj_t* actor)
  1234. {
  1235.     A_Fall (actor);
  1236.     A_PainShootSkull (actor, actor->angle+ANG90);
  1237.     A_PainShootSkull (actor, actor->angle+ANG180);
  1238.     A_PainShootSkull (actor, actor->angle+ANG270);
  1239. }
  1240. void A_Scream (mobj_t* actor)
  1241. {
  1242.     int sound;
  1243.     switch (actor->info->deathsound)
  1244.     {
  1245.       case 0:
  1246. return;
  1247.       case sfx_podth1:
  1248.       case sfx_podth2:
  1249.       case sfx_podth3:
  1250. sound = sfx_podth1 + P_Random ()%3;
  1251. break;
  1252.       case sfx_bgdth1:
  1253.       case sfx_bgdth2:
  1254. sound = sfx_bgdth1 + P_Random ()%2;
  1255. break;
  1256.       default:
  1257. sound = actor->info->deathsound;
  1258. break;
  1259.     }
  1260.     // Check for bosses.
  1261.     if (actor->type==MT_SPIDER
  1262. || actor->type == MT_CYBORG)
  1263.     {
  1264. // full volume
  1265. S_StartSound (NULL, sound);
  1266.     }
  1267.     else
  1268. S_StartSound (actor, sound);
  1269. }
  1270. void A_XScream (mobj_t* actor)
  1271. {
  1272.     S_StartSound (actor, sfx_slop);
  1273. }
  1274. void A_Pain (mobj_t* actor)
  1275. {
  1276.     if (actor->info->painsound)
  1277. S_StartSound (actor, actor->info->painsound);
  1278. }
  1279. void A_Fall (mobj_t *actor)
  1280. {
  1281.     // actor is on ground, it can be walked over
  1282.     actor->flags &= ~MF_SOLID;
  1283.     // So change this if corpse objects
  1284.     // are meant to be obstacles.
  1285. }
  1286. //
  1287. // A_Explode
  1288. //
  1289. void A_Explode (mobj_t* thingy)
  1290. {
  1291.     P_RadiusAttack ( thingy, thingy->target, 128 );
  1292. }
  1293. //
  1294. // A_BossDeath
  1295. // Possibly trigger special effects
  1296. // if on first boss level
  1297. //
  1298. void A_BossDeath (mobj_t* mo)
  1299. {
  1300.     thinker_t* th;
  1301.     mobj_t* mo2;
  1302.     line_t junk;
  1303.     int i;
  1304.     if ( gamemode == commercial)
  1305.     {
  1306. if (gamemap != 7)
  1307.     return;
  1308. if ((mo->type != MT_FATSO)
  1309.     && (mo->type != MT_BABY))
  1310.     return;
  1311.     }
  1312.     else
  1313.     {
  1314. switch(gameepisode)
  1315. {
  1316.   case 1:
  1317.     if (gamemap != 8)
  1318. return;
  1319.     if (mo->type != MT_BRUISER)
  1320. return;
  1321.     break;
  1322.     
  1323.   case 2:
  1324.     if (gamemap != 8)
  1325. return;
  1326.     if (mo->type != MT_CYBORG)
  1327. return;
  1328.     break;
  1329.     
  1330.   case 3:
  1331.     if (gamemap != 8)
  1332. return;
  1333.     
  1334.     if (mo->type != MT_SPIDER)
  1335. return;
  1336.     
  1337.     break;
  1338.     
  1339.   case 4:
  1340.     switch(gamemap)
  1341.     {
  1342.       case 6:
  1343. if (mo->type != MT_CYBORG)
  1344.     return;
  1345. break;
  1346.       case 8: 
  1347. if (mo->type != MT_SPIDER)
  1348.     return;
  1349. break;
  1350.       default:
  1351. return;
  1352. break;
  1353.     }
  1354.     break;
  1355.     
  1356.   default:
  1357.     if (gamemap != 8)
  1358. return;
  1359.     break;
  1360. }
  1361.     }
  1362.     
  1363.     // make sure there is a player alive for victory
  1364.     for (i=0 ; i<MAXPLAYERS ; i++)
  1365. if (playeringame[i] && players[i].health > 0)
  1366.     break;
  1367.     
  1368.     if (i==MAXPLAYERS)
  1369. return; // no one left alive, so do not end game
  1370.     
  1371.     // scan the remaining thinkers to see
  1372.     // if all bosses are dead
  1373.     for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
  1374.     {
  1375. if (th->function.acp1 != (actionf_p1)P_MobjThinker)
  1376.     continue;
  1377. mo2 = (mobj_t *)th;
  1378. if (mo2 != mo
  1379.     && mo2->type == mo->type
  1380.     && mo2->health > 0)
  1381. {
  1382.     // other boss not dead
  1383.     return;
  1384. }
  1385.     }
  1386.     // victory!
  1387.     if ( gamemode == commercial)
  1388.     {
  1389. if (gamemap == 7)
  1390. {
  1391.     if (mo->type == MT_FATSO)
  1392.     {
  1393. junk.tag = 666;
  1394. EV_DoFloor(&junk,lowerFloorToLowest);
  1395. return;
  1396.     }
  1397.     
  1398.     if (mo->type == MT_BABY)
  1399.     {
  1400. junk.tag = 667;
  1401. EV_DoFloor(&junk,raiseToTexture);
  1402. return;
  1403.     }
  1404. }
  1405.     }
  1406.     else
  1407.     {
  1408. switch(gameepisode)
  1409. {
  1410.   case 1:
  1411.     junk.tag = 666;
  1412.     EV_DoFloor (&junk, lowerFloorToLowest);
  1413.     return;
  1414.     break;
  1415.     
  1416.   case 4:
  1417.     switch(gamemap)
  1418.     {
  1419.       case 6:
  1420. junk.tag = 666;
  1421. EV_DoDoor (&junk, blazeOpen);
  1422. return;
  1423. break;
  1424.       case 8:
  1425. junk.tag = 666;
  1426. EV_DoFloor (&junk, lowerFloorToLowest);
  1427. return;
  1428. break;
  1429.     }
  1430. }
  1431.     }
  1432.     G_ExitLevel ();
  1433. }
  1434. void A_Hoof (mobj_t* mo)
  1435. {
  1436.     S_StartSound (mo, sfx_hoof);
  1437.     A_Chase (mo);
  1438. }
  1439. void A_Metal (mobj_t* mo)
  1440. {
  1441.     S_StartSound (mo, sfx_metal);
  1442.     A_Chase (mo);
  1443. }
  1444. void A_BabyMetal (mobj_t* mo)
  1445. {
  1446.     S_StartSound (mo, sfx_bspwlk);
  1447.     A_Chase (mo);
  1448. }
  1449. void
  1450. A_OpenShotgun2
  1451. ( player_t* player,
  1452.   pspdef_t* psp )
  1453. {
  1454.     S_StartSound (player->mo, sfx_dbopn);
  1455. }
  1456. void
  1457. A_LoadShotgun2
  1458. ( player_t* player,
  1459.   pspdef_t* psp )
  1460. {
  1461.     S_StartSound (player->mo, sfx_dbload);
  1462. }
  1463. void
  1464. A_ReFire
  1465. ( player_t* player,
  1466.   pspdef_t* psp );
  1467. void
  1468. A_CloseShotgun2
  1469. ( player_t* player,
  1470.   pspdef_t* psp )
  1471. {
  1472.     S_StartSound (player->mo, sfx_dbcls);
  1473.     A_ReFire(player,psp);
  1474. }
  1475. mobj_t* braintargets[32];
  1476. int numbraintargets;
  1477. int braintargeton;
  1478. void A_BrainAwake (mobj_t* mo)
  1479. {
  1480.     thinker_t* thinker;
  1481.     mobj_t* m;
  1482.     // find all the target spots
  1483.     numbraintargets = 0;
  1484.     braintargeton = 0;
  1485.     thinker = thinkercap.next;
  1486.     for (thinker = thinkercap.next ;
  1487.  thinker != &thinkercap ;
  1488.  thinker = thinker->next)
  1489.     {
  1490. if (thinker->function.acp1 != (actionf_p1)P_MobjThinker)
  1491.     continue; // not a mobj
  1492. m = (mobj_t *)thinker;
  1493. if (m->type == MT_BOSSTARGET )
  1494. {
  1495.     braintargets[numbraintargets] = m;
  1496.     numbraintargets++;
  1497. }
  1498.     }
  1499.     S_StartSound (NULL,sfx_bossit);
  1500. }
  1501. void A_BrainPain (mobj_t* mo)
  1502. {
  1503.     S_StartSound (NULL,sfx_bospn);
  1504. }
  1505. void A_BrainScream (mobj_t* mo)
  1506. {
  1507.     int x;
  1508.     int y;
  1509.     int z;
  1510.     mobj_t* th;
  1511.     for (x=mo->x - 196*FRACUNIT ; x< mo->x + 320*FRACUNIT ; x+= FRACUNIT*8)
  1512.     {
  1513. y = mo->y - 320*FRACUNIT;
  1514. z = 128 + P_Random()*2*FRACUNIT;
  1515. th = P_SpawnMobj (x,y,z, MT_ROCKET);
  1516. th->momz = P_Random()*512;
  1517. P_SetMobjState (th, S_BRAINEXPLODE1);
  1518. th->tics -= P_Random()&7;
  1519. if (th->tics < 1)
  1520.     th->tics = 1;
  1521.     }
  1522.     S_StartSound (NULL,sfx_bosdth);
  1523. }
  1524. void A_BrainExplode (mobj_t* mo)
  1525. {
  1526.     int x;
  1527.     int y;
  1528.     int z;
  1529.     mobj_t* th;
  1530.     x = mo->x + (P_Random () - P_Random ())*2048;
  1531.     y = mo->y;
  1532.     z = 128 + P_Random()*2*FRACUNIT;
  1533.     th = P_SpawnMobj (x,y,z, MT_ROCKET);
  1534.     th->momz = P_Random()*512;
  1535.     P_SetMobjState (th, S_BRAINEXPLODE1);
  1536.     th->tics -= P_Random()&7;
  1537.     if (th->tics < 1)
  1538. th->tics = 1;
  1539. }
  1540. void A_BrainDie (mobj_t* mo)
  1541. {
  1542.     G_ExitLevel ();
  1543. }
  1544. void A_BrainSpit (mobj_t* mo)
  1545. {
  1546.     mobj_t* targ;
  1547.     mobj_t* newmobj;
  1548.     
  1549.     static int easy = 0;
  1550.     easy ^= 1;
  1551.     if (gameskill <= sk_easy && (!easy))
  1552. return;
  1553.     // shoot a cube at current target
  1554.     targ = braintargets[braintargeton];
  1555.     braintargeton = (braintargeton+1)%numbraintargets;
  1556.     // spawn brain missile
  1557.     newmobj = P_SpawnMissile (mo, targ, MT_SPAWNSHOT);
  1558.     newmobj->target = targ;
  1559.     newmobj->reactiontime =
  1560. ((targ->y - mo->y)/newmobj->momy) / newmobj->state->tics;
  1561.     S_StartSound(NULL, sfx_bospit);
  1562. }
  1563. void A_SpawnFly (mobj_t* mo);
  1564. // travelling cube sound
  1565. void A_SpawnSound (mobj_t* mo)
  1566. {
  1567.     S_StartSound (mo,sfx_boscub);
  1568.     A_SpawnFly(mo);
  1569. }
  1570. void A_SpawnFly (mobj_t* mo)
  1571. {
  1572.     mobj_t* newmobj;
  1573.     mobj_t* fog;
  1574.     mobj_t* targ;
  1575.     int r;
  1576.     mobjtype_t type;
  1577.     if (--mo->reactiontime)
  1578. return; // still flying
  1579.     targ = mo->target;
  1580.     // First spawn teleport fog.
  1581.     fog = P_SpawnMobj (targ->x, targ->y, targ->z, MT_SPAWNFIRE);
  1582.     S_StartSound (fog, sfx_telept);
  1583.     // Randomly select monster to spawn.
  1584.     r = P_Random ();
  1585.     // Probability distribution (kind of :),
  1586.     // decreasing likelihood.
  1587.     if ( r<50 )
  1588. type = MT_TROOP;
  1589.     else if (r<90)
  1590. type = MT_SERGEANT;
  1591.     else if (r<120)
  1592. type = MT_SHADOWS;
  1593.     else if (r<130)
  1594. type = MT_PAIN;
  1595.     else if (r<160)
  1596. type = MT_HEAD;
  1597.     else if (r<162)
  1598. type = MT_VILE;
  1599.     else if (r<172)
  1600. type = MT_UNDEAD;
  1601.     else if (r<192)
  1602. type = MT_BABY;
  1603.     else if (r<222)
  1604. type = MT_FATSO;
  1605.     else if (r<246)
  1606. type = MT_KNIGHT;
  1607.     else
  1608. type = MT_BRUISER;
  1609.     newmobj = P_SpawnMobj (targ->x, targ->y, targ->z, type);
  1610.     if (P_LookForPlayers (newmobj, true) )
  1611. P_SetMobjState (newmobj, newmobj->info->seestate);
  1612.     // telefrag anything in this spot
  1613.     P_TeleportMove (newmobj, newmobj->x, newmobj->y);
  1614.     // remove self (i.e., cube).
  1615.     P_RemoveMobj (mo);
  1616. }
  1617. void A_PlayerScream (mobj_t* mo)
  1618. {
  1619.     // Default death sound.
  1620.     int sound = sfx_pldeth;
  1621.     if ( (gamemode == commercial)
  1622. &&  (mo->health < -50))
  1623.     {
  1624. // IF THE PLAYER DIES
  1625. // LESS THAN -50% WITHOUT GIBBING
  1626. sound = sfx_pdiehi;
  1627.     }
  1628.     
  1629.     S_StartSound (mo, sound);
  1630. }