1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
6 // Copyright (C) 1993-1996 by id Software, Inc.
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.
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
20 // Enemy thinking, AI.
21 // Action Pointer Functions
22 // that are associated with states/frames.
24 //-----------------------------------------------------------------------------
27 rcsid[] = "$Id: p_enemy.c,v 1.5 1997/02/03 22:45:11 b1 Exp $";
66 // P_NewChaseDir related LUT.
68 dirtype_t opposite[] =
70 DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST,
71 DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_NODIR
76 DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST
83 void A_Fall (void *actor, void*);
88 // Enemies are allways spawned
89 // with targetplayer = -1, threshold = 0
90 // Most monsters are spawned unaware of all players,
91 // but some can be made preaware
96 // Called by P_NoiseAlert.
97 // Recursively traverse adjacent sectors,
98 // sound blocking lines cut off traversal.
112 // wake up all monsters in this sector
113 if (sec->validcount == validcount
114 && sec->soundtraversed <= soundblocks+1)
116 return; // already flooded
119 sec->validcount = validcount;
120 sec->soundtraversed = soundblocks+1;
121 sec->soundtarget = soundtarget;
123 for (i=0 ;i<sec->linecount ; i++)
125 check = sec->lines[i];
126 if (! (check->flags & ML_TWOSIDED) )
129 P_LineOpening (check);
132 continue; // closed door
134 if ( sides[ check->sidenum[0] ].sector == sec)
135 other = sides[ check->sidenum[1] ] .sector;
137 other = sides[ check->sidenum[0] ].sector;
139 if (check->flags & ML_SOUNDBLOCK)
142 P_RecursiveSound (other, 1);
145 P_RecursiveSound (other, soundblocks);
153 // If a monster yells at a player,
154 // it will alert other monsters to the player.
161 soundtarget = target;
163 P_RecursiveSound (emmiter->subsector->sector, 0);
172 boolean P_CheckMeleeRange (mobj_t* actor)
181 dist = P_AproxDistance (pl->x-actor->x, pl->y-actor->y);
183 if (dist >= MELEERANGE-20*FRACUNIT+pl->info->radius)
186 if (! P_CheckSight (actor, actor->target) )
193 // P_CheckMissileRange
195 boolean P_CheckMissileRange (mobj_t* actor)
199 if (! P_CheckSight (actor, actor->target) )
202 if ( actor->flags & MF_JUSTHIT )
204 // the target just hit the enemy,
206 actor->flags &= ~MF_JUSTHIT;
210 if (actor->reactiontime)
211 return false; // do not attack yet
213 // OPTIMIZE: get this from a global checksight
214 dist = P_AproxDistance ( actor->x-actor->target->x,
215 actor->y-actor->target->y) - 64*FRACUNIT;
217 if (!actor->info->meleestate)
218 dist -= 128*FRACUNIT; // no melee attack, so fire more
222 if (actor->type == MT_VILE)
225 return false; // too far away
229 if (actor->type == MT_UNDEAD)
232 return false; // close for fist attack
237 if (actor->type == MT_CYBORG
238 || actor->type == MT_SPIDER
239 || actor->type == MT_SKULL)
247 if (actor->type == MT_CYBORG && dist > 160)
250 if (P_Random () < dist)
259 // Move in the current direction,
260 // returns false if the move is blocked.
262 fixed_t xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000};
263 fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000};
265 #define MAXSPECIALCROSS 8
267 extern line_t* spechit[MAXSPECIALCROSS];
268 extern int numspechit;
270 boolean P_Move (mobj_t* actor)
277 // warning: 'catch', 'throw', and 'try'
278 // are all C++ reserved words
282 if (actor->movedir == DI_NODIR)
285 if ((unsigned)actor->movedir >= 8)
286 I_Error ("Weird actor->movedir!");
288 tryx = actor->x + actor->info->speed*xspeed[actor->movedir];
289 tryy = actor->y + actor->info->speed*yspeed[actor->movedir];
291 try_ok = P_TryMove (actor, tryx, tryy);
296 if (actor->flags & MF_FLOAT && floatok)
298 // must adjust height
299 if (actor->z < tmfloorz)
300 actor->z += FLOATSPEED;
302 actor->z -= FLOATSPEED;
304 actor->flags |= MF_INFLOAT;
311 actor->movedir = DI_NODIR;
315 ld = spechit[numspechit];
316 // if the special is not a door
317 // that can be opened,
319 if (P_UseSpecialLine (actor, ld,0))
326 actor->flags &= ~MF_INFLOAT;
330 if (! (actor->flags & MF_FLOAT) )
331 actor->z = actor->floorz;
338 // Attempts to move actor on
339 // in its current (ob->moveangle) direction.
340 // If blocked by either a wall or an actor
342 // If move is either clear or blocked only by a door,
343 // returns TRUE and sets...
344 // If a door is in the way,
345 // an OpenDoor call is made to start it opening.
347 boolean P_TryWalk (mobj_t* actor)
354 actor->movecount = P_Random()&15;
361 void P_NewChaseDir (mobj_t* actor)
371 dirtype_t turnaround;
374 I_Error ("P_NewChaseDir: called with no target");
376 olddir = actor->movedir;
377 turnaround=opposite[olddir];
379 deltax = actor->target->x - actor->x;
380 deltay = actor->target->y - actor->y;
382 if (deltax>10*FRACUNIT)
384 else if (deltax<-10*FRACUNIT)
389 if (deltay<-10*FRACUNIT)
391 else if (deltay>10*FRACUNIT)
400 actor->movedir = diags[((deltay<0)<<1)+(deltax>0)];
401 if (actor->movedir != turnaround && P_TryWalk(actor))
405 // try other directions
407 || abs(deltay)>abs(deltax))
414 if (d[1]==turnaround)
416 if (d[2]==turnaround)
421 actor->movedir = d[1];
422 if (P_TryWalk(actor))
424 // either moved forward or attacked
431 actor->movedir =d[2];
433 if (P_TryWalk(actor))
437 // there is no direct path to the player,
438 // so pick another direction.
439 if (olddir!=DI_NODIR)
441 actor->movedir =olddir;
443 if (P_TryWalk(actor))
447 // randomly determine direction of search
454 if (tdir!=turnaround)
456 actor->movedir =tdir;
458 if ( P_TryWalk(actor) )
465 for ( tdir=DI_SOUTHEAST;
469 if (tdir!=turnaround)
471 actor->movedir =tdir;
473 if ( P_TryWalk(actor) )
479 if (turnaround != DI_NODIR)
481 actor->movedir =turnaround;
482 if ( P_TryWalk(actor) )
486 actor->movedir = DI_NODIR; // can not move
493 // If allaround is false, only look 180 degrees in front.
494 // Returns true if a player is targeted.
508 stop = (actor->lastlook-1)&3;
510 for ( ; ; actor->lastlook = (actor->lastlook+1)&3 )
512 if (!playeringame[actor->lastlook])
516 || actor->lastlook == stop)
522 player = &players[actor->lastlook];
524 if (player->health <= 0)
527 if (!P_CheckSight (actor, player->mo))
528 continue; // out of sight
532 an = R_PointToAngle2 (actor->x,
538 if (an > ANG90 && an < ANG270)
540 dist = P_AproxDistance (player->mo->x - actor->x,
541 player->mo->y - actor->y);
542 // if real close, react anyway
543 if (dist > MELEERANGE)
544 continue; // behind back
548 actor->target = player->mo;
556 // DOOM II special, map 32.
557 // Uses special tag 666.
559 void A_KeenDie (void *_mo, void*)
561 mobj_t *mo = (mobj_t*)_mo;
568 // scan the remaining thinkers
569 // to see if all Keens are dead
570 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
572 if (th->function != P_MobjThinker)
577 && mo2->type == mo->type
580 // other Keen not dead
586 EV_DoDoor(&junk,Open);
596 // Stay in state until a player is sighted.
598 void A_Look (void *_actor, void*)
600 mobj_t *actor = (mobj_t*)_actor;
603 actor->threshold = 0; // any shot will wake up
604 targ = actor->subsector->sector->soundtarget;
607 && (targ->flags & MF_SHOOTABLE) )
609 actor->target = targ;
611 if ( actor->flags & MF_AMBUSH )
613 if (P_CheckSight (actor, actor->target))
621 if (!P_LookForPlayers (actor, false) )
624 // go into chase state
626 if (actor->info->seesound)
630 switch (actor->info->seesound)
635 sound = sfx_posit1+P_Random()%3;
640 sound = sfx_bgsit1+P_Random()%2;
644 sound = actor->info->seesound;
648 if (actor->type==MT_SPIDER
649 || actor->type == MT_CYBORG)
652 S_StartSound (NULL, sound);
655 S_StartSound (actor, sound);
658 P_SetMobjState (actor, actor->info->seestate);
664 // Actor has a melee attack,
665 // so it tries to close as fast as possible
667 void A_Chase (void *_actor, void*)
669 mobj_t *actor = (mobj_t*)_actor;
672 if (actor->reactiontime)
673 actor->reactiontime--;
676 // modify target threshold
677 if (actor->threshold)
680 || actor->target->health <= 0)
682 actor->threshold = 0;
688 // turn towards movement direction if not there yet
689 if (actor->movedir < 8)
691 actor->angle &= (7<<29);
692 delta = actor->angle - (actor->movedir << 29);
695 actor->angle -= ANG90/2;
697 actor->angle += ANG90/2;
701 || !(actor->target->flags&MF_SHOOTABLE))
703 // look for a new target
704 if (P_LookForPlayers(actor,true))
705 return; // got a new target
707 P_SetMobjState (actor, actor->info->spawnstate);
711 // do not attack twice in a row
712 if (actor->flags & MF_JUSTATTACKED)
714 actor->flags &= ~MF_JUSTATTACKED;
715 if (gameskill != sk_nightmare && !fastparm)
716 P_NewChaseDir (actor);
720 // check for melee attack
721 if (actor->info->meleestate
722 && P_CheckMeleeRange (actor))
724 if (actor->info->attacksound)
725 S_StartSound (actor, actor->info->attacksound);
727 P_SetMobjState (actor, actor->info->meleestate);
731 // check for missile attack
732 if (actor->info->missilestate)
734 if (gameskill < sk_nightmare
735 && !fastparm && actor->movecount)
740 if (!P_CheckMissileRange (actor))
743 P_SetMobjState (actor, actor->info->missilestate);
744 actor->flags |= MF_JUSTATTACKED;
750 // possibly choose another target
753 && !P_CheckSight (actor, actor->target) )
755 if (P_LookForPlayers(actor,true))
756 return; // got a new target
759 // chase towards player
760 if (--actor->movecount<0
763 P_NewChaseDir (actor);
767 if (actor->info->activesound
770 S_StartSound (actor, actor->info->activesound);
778 void A_FaceTarget (void *_actor, void*)
780 mobj_t *actor = (mobj_t*)_actor;
784 actor->flags &= ~MF_AMBUSH;
786 actor->angle = R_PointToAngle2 (actor->x,
791 if (actor->target->flags & MF_SHADOW)
792 actor->angle += (P_Random()-P_Random())<<21;
799 void A_PosAttack (void *_actor, void*)
801 mobj_t *actor = (mobj_t*)_actor;
809 A_FaceTarget (actor, NULL);
810 angle = actor->angle;
811 slope = P_AimLineAttack (actor, angle, MISSILERANGE);
813 S_StartSound (actor, sfx_pistol);
814 angle += (P_Random()-P_Random())<<20;
815 damage = ((P_Random()%5)+1)*3;
816 P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
819 void A_SPosAttack (void *_actor, void*)
821 mobj_t *actor = (mobj_t*)_actor;
831 S_StartSound (actor, sfx_shotgn);
832 A_FaceTarget (actor, NULL);
833 bangle = actor->angle;
834 slope = P_AimLineAttack (actor, bangle, MISSILERANGE);
836 for (i=0 ; i<3 ; i++)
838 angle = bangle + ((P_Random()-P_Random())<<20);
839 damage = ((P_Random()%5)+1)*3;
840 P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
844 void A_CPosAttack (void *_actor, void*)
846 mobj_t *actor = (mobj_t*)_actor;
855 S_StartSound (actor, sfx_shotgn);
856 A_FaceTarget (actor, NULL);
857 bangle = actor->angle;
858 slope = P_AimLineAttack (actor, bangle, MISSILERANGE);
860 angle = bangle + ((P_Random()-P_Random())<<20);
861 damage = ((P_Random()%5)+1)*3;
862 P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
865 void A_CPosRefire (void *_actor, void*)
867 mobj_t *actor = (mobj_t*)_actor;
868 // keep firing unless target got out of sight
869 A_FaceTarget (actor, NULL);
871 if (P_Random () < 40)
875 || actor->target->health <= 0
876 || !P_CheckSight (actor, actor->target) )
878 P_SetMobjState (actor, actor->info->seestate);
883 void A_SpidRefire (void *_actor, void*)
885 mobj_t *actor = (mobj_t*)_actor;
886 // keep firing unless target got out of sight
887 A_FaceTarget (actor, NULL);
889 if (P_Random () < 10)
893 || actor->target->health <= 0
894 || !P_CheckSight (actor, actor->target) )
896 P_SetMobjState (actor, actor->info->seestate);
900 void A_BspiAttack (void *_actor, void*)
902 mobj_t *actor = (mobj_t*)_actor;
906 A_FaceTarget (actor, NULL);
909 P_SpawnMissile (actor, actor->target, MT_ARACHPLAZ);
916 void A_TroopAttack (void *_actor, void*)
918 mobj_t *actor = (mobj_t*)_actor;
924 A_FaceTarget (actor, NULL);
925 if (P_CheckMeleeRange (actor))
927 S_StartSound (actor, sfx_claw);
928 damage = (P_Random()%8+1)*3;
929 P_DamageMobj (actor->target, actor, actor, damage);
935 P_SpawnMissile (actor, actor->target, MT_TROOPSHOT);
939 void A_SargAttack (void *_actor, void*)
941 mobj_t *actor = (mobj_t*)_actor;
947 A_FaceTarget (actor, NULL);
948 if (P_CheckMeleeRange (actor))
950 damage = ((P_Random()%10)+1)*4;
951 P_DamageMobj (actor->target, actor, actor, damage);
955 void A_HeadAttack (void *_actor, void*)
957 mobj_t *actor = (mobj_t*)_actor;
963 A_FaceTarget (actor, NULL);
964 if (P_CheckMeleeRange (actor))
966 damage = (P_Random()%6+1)*10;
967 P_DamageMobj (actor->target, actor, actor, damage);
972 P_SpawnMissile (actor, actor->target, MT_HEADSHOT);
975 void A_CyberAttack (void *_actor, void*)
977 mobj_t *actor = (mobj_t*)_actor;
981 A_FaceTarget (actor, NULL);
982 P_SpawnMissile (actor, actor->target, MT_ROCKET);
986 void A_BruisAttack (void *_actor, void*)
988 mobj_t *actor = (mobj_t*)_actor;
994 if (P_CheckMeleeRange (actor))
996 S_StartSound (actor, sfx_claw);
997 damage = (P_Random()%8+1)*10;
998 P_DamageMobj (actor->target, actor, actor, damage);
1003 P_SpawnMissile (actor, actor->target, MT_BRUISERSHOT);
1010 void A_SkelMissile (void *_actor, void*)
1012 mobj_t *actor = (mobj_t*)_actor;
1018 A_FaceTarget (actor, NULL);
1019 actor->z += 16*FRACUNIT; // so missile spawns higher
1020 mo = P_SpawnMissile (actor, actor->target, MT_TRACER);
1021 actor->z -= 16*FRACUNIT; // back to normal
1025 mo->tracer = actor->target;
1028 int TRACEANGLE = 0xc000000;
1030 void A_Tracer (void *_actor, void*)
1032 mobj_t *actor = (mobj_t*)_actor;
1042 // spawn a puff of smoke behind the rocket
1043 P_SpawnPuff (actor->x, actor->y, actor->z);
1045 th = P_SpawnMobj (actor->x-actor->momx,
1046 actor->y-actor->momy,
1047 actor->z, MT_SMOKE);
1049 th->momz = FRACUNIT;
1050 th->tics -= P_Random()&3;
1055 dest = actor->tracer;
1057 if (!dest || dest->health <= 0)
1061 exact = R_PointToAngle2 (actor->x,
1066 if (exact != actor->angle)
1068 if (exact - actor->angle > 0x80000000)
1070 actor->angle -= TRACEANGLE;
1071 if (exact - actor->angle < 0x80000000)
1072 actor->angle = exact;
1076 actor->angle += TRACEANGLE;
1077 if (exact - actor->angle > 0x80000000)
1078 actor->angle = exact;
1082 exact = actor->angle>>ANGLETOFINESHIFT;
1083 actor->momx = FixedMul (actor->info->speed, finecosine[exact]);
1084 actor->momy = FixedMul (actor->info->speed, finesine[exact]);
1087 dist = P_AproxDistance (dest->x - actor->x,
1088 dest->y - actor->y);
1090 dist = dist / actor->info->speed;
1094 slope = (dest->z+40*FRACUNIT - actor->z) / dist;
1096 if (slope < actor->momz)
1097 actor->momz -= FRACUNIT/8;
1099 actor->momz += FRACUNIT/8;
1103 void A_SkelWhoosh (void *_actor, void*)
1105 mobj_t *actor = (mobj_t*)_actor;
1108 A_FaceTarget (actor, NULL);
1109 S_StartSound (actor,sfx_skeswg);
1112 void A_SkelFist (void *_actor, void*)
1114 mobj_t *actor = (mobj_t*)_actor;
1120 A_FaceTarget (actor, NULL);
1122 if (P_CheckMeleeRange (actor))
1124 damage = ((P_Random()%10)+1)*6;
1125 S_StartSound (actor, sfx_skepch);
1126 P_DamageMobj (actor->target, actor, actor, damage);
1134 // Detect a corpse that could be raised.
1141 boolean PIT_VileCheck (mobj_t* thing)
1146 if (!(thing->flags & MF_CORPSE) )
1147 return true; // not a monster
1149 if (thing->tics != -1)
1150 return true; // not lying still yet
1152 if (thing->info->raisestate == S_NULL)
1153 return true; // monster doesn't have a raise state
1155 maxdist = thing->info->radius + mobjinfo[MT_VILE].radius;
1157 if ( abs(thing->x - viletryx) > maxdist
1158 || abs(thing->y - viletryy) > maxdist )
1159 return true; // not actually touching
1162 corpsehit->momx = corpsehit->momy = 0;
1163 corpsehit->height <<= 2;
1164 check = P_CheckPosition (corpsehit, corpsehit->x, corpsehit->y);
1165 corpsehit->height >>= 2;
1168 return true; // doesn't fit here
1170 return false; // got one, so stop checking
1177 // Check for ressurecting a body
1179 void A_VileChase (void *_actor, void*)
1181 mobj_t *actor = (mobj_t*)_actor;
1193 if (actor->movedir != DI_NODIR)
1195 // check for corpses to raise
1197 actor->x + actor->info->speed*xspeed[actor->movedir];
1199 actor->y + actor->info->speed*yspeed[actor->movedir];
1201 xl = (viletryx - bmaporgx - MAXRADIUS*2)>>MAPBLOCKSHIFT;
1202 xh = (viletryx - bmaporgx + MAXRADIUS*2)>>MAPBLOCKSHIFT;
1203 yl = (viletryy - bmaporgy - MAXRADIUS*2)>>MAPBLOCKSHIFT;
1204 yh = (viletryy - bmaporgy + MAXRADIUS*2)>>MAPBLOCKSHIFT;
1207 for (bx=xl ; bx<=xh ; bx++)
1209 for (by=yl ; by<=yh ; by++)
1211 // Call PIT_VileCheck to check
1212 // whether object is a corpse
1213 // that canbe raised.
1214 if (!P_BlockThingsIterator(bx,by,PIT_VileCheck))
1217 temp = actor->target;
1218 actor->target = corpsehit;
1219 A_FaceTarget (actor, NULL);
1220 actor->target = temp;
1222 P_SetMobjState (actor, S_VILE_HEAL1);
1223 S_StartSound (corpsehit, sfx_slop);
1224 info = corpsehit->info;
1226 P_SetMobjState (corpsehit,info->raisestate);
1227 corpsehit->height <<= 2;
1228 corpsehit->flags = info->flags;
1229 corpsehit->health = info->spawnhealth;
1230 corpsehit->target = NULL;
1238 // Return to normal attack.
1239 A_Chase (actor, NULL);
1246 void A_VileStart (void *_actor, void*)
1248 mobj_t *actor = (mobj_t*)_actor;
1249 S_StartSound (actor, sfx_vilatk);
1255 // Keep fire in front of player unless out of sight
1257 void A_Fire (void *_actor, void*);
1259 void A_StartFire (void *_actor, void*)
1261 mobj_t *actor = (mobj_t*)_actor;
1262 S_StartSound(actor,sfx_flamst);
1263 A_Fire(actor, NULL);
1266 void A_FireCrackle (void *_actor, void*)
1268 mobj_t *actor = (mobj_t*)_actor;
1269 S_StartSound(actor,sfx_flame);
1270 A_Fire(actor, NULL);
1273 void A_Fire (void *_actor, void*)
1275 mobj_t *actor = (mobj_t*)_actor;
1279 dest = actor->tracer;
1283 // don't move it if the vile lost sight
1284 if (!P_CheckSight (actor->target, dest) )
1287 an = dest->angle >> ANGLETOFINESHIFT;
1289 P_UnsetThingPosition (actor);
1290 actor->x = dest->x + FixedMul (24*FRACUNIT, finecosine[an]);
1291 actor->y = dest->y + FixedMul (24*FRACUNIT, finesine[an]);
1293 P_SetThingPosition (actor);
1300 // Spawn the hellfire
1302 void A_VileTarget (void *_actor, void*)
1304 mobj_t *actor = (mobj_t*)_actor;
1310 A_FaceTarget (actor, NULL);
1312 fog = P_SpawnMobj (actor->target->x,
1314 actor->target->z, MT_FIRE);
1316 actor->tracer = fog;
1317 fog->target = actor;
1318 fog->tracer = actor->target;
1328 void A_VileAttack (void *_actor, void*)
1330 mobj_t *actor = (mobj_t*)_actor;
1337 A_FaceTarget (actor, NULL);
1339 if (!P_CheckSight (actor, actor->target) )
1342 S_StartSound (actor, sfx_barexp);
1343 P_DamageMobj (actor->target, actor, actor, 20);
1344 actor->target->momz = 1000*FRACUNIT/actor->target->info->mass;
1346 an = actor->angle >> ANGLETOFINESHIFT;
1348 fire = actor->tracer;
1353 // move the fire between the vile and the player
1354 fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]);
1355 fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]);
1356 P_RadiusAttack (fire, actor, 70 );
1364 // firing three missiles (bruisers)
1365 // in three different directions?
1366 // Doesn't look like it.
1368 #define FATSPREAD (ANG90/8)
1370 void A_FatRaise (void *_actor, void*)
1372 mobj_t *actor = (mobj_t*)_actor;
1373 A_FaceTarget (actor, NULL);
1374 S_StartSound (actor, sfx_manatk);
1378 void A_FatAttack1 (void *_actor, void*)
1380 mobj_t *actor = (mobj_t*)_actor;
1384 A_FaceTarget (actor, NULL);
1385 // Change direction to ...
1386 actor->angle += FATSPREAD;
1387 P_SpawnMissile (actor, actor->target, MT_FATSHOT);
1389 mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
1390 mo->angle += FATSPREAD;
1391 an = mo->angle >> ANGLETOFINESHIFT;
1392 mo->momx = FixedMul (mo->info->speed, finecosine[an]);
1393 mo->momy = FixedMul (mo->info->speed, finesine[an]);
1396 void A_FatAttack2 (void *_actor, void*)
1398 mobj_t *actor = (mobj_t*)_actor;
1402 A_FaceTarget (actor, NULL);
1403 // Now here choose opposite deviation.
1404 actor->angle -= FATSPREAD;
1405 P_SpawnMissile (actor, actor->target, MT_FATSHOT);
1407 mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
1408 mo->angle -= FATSPREAD*2;
1409 an = mo->angle >> ANGLETOFINESHIFT;
1410 mo->momx = FixedMul (mo->info->speed, finecosine[an]);
1411 mo->momy = FixedMul (mo->info->speed, finesine[an]);
1414 void A_FatAttack3 (void *_actor, void*)
1416 mobj_t *actor = (mobj_t*)_actor;
1420 A_FaceTarget (actor, NULL);
1422 mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
1423 mo->angle -= FATSPREAD/2;
1424 an = mo->angle >> ANGLETOFINESHIFT;
1425 mo->momx = FixedMul (mo->info->speed, finecosine[an]);
1426 mo->momy = FixedMul (mo->info->speed, finesine[an]);
1428 mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
1429 mo->angle += FATSPREAD/2;
1430 an = mo->angle >> ANGLETOFINESHIFT;
1431 mo->momx = FixedMul (mo->info->speed, finecosine[an]);
1432 mo->momy = FixedMul (mo->info->speed, finesine[an]);
1438 // Fly at the player like a missile.
1440 #define SKULLSPEED (20*FRACUNIT)
1442 void A_SkullAttack (void *_actor, void*)
1444 mobj_t *actor = (mobj_t*)_actor;
1452 dest = actor->target;
1453 actor->flags |= MF_SKULLFLY;
1455 S_StartSound (actor, actor->info->attacksound);
1456 A_FaceTarget (actor, NULL);
1457 an = actor->angle >> ANGLETOFINESHIFT;
1458 actor->momx = FixedMul (SKULLSPEED, finecosine[an]);
1459 actor->momy = FixedMul (SKULLSPEED, finesine[an]);
1460 dist = P_AproxDistance (dest->x - actor->x, dest->y - actor->y);
1461 dist = dist / SKULLSPEED;
1465 actor->momz = (dest->z+(dest->height>>1) - actor->z) / dist;
1471 // Spawn a lost soul and launch it at the target
1486 thinker_t* currentthinker;
1488 // count total number of skull currently on the level
1491 currentthinker = thinkercap.next;
1492 while (currentthinker != &thinkercap)
1494 if ( (currentthinker->function == P_MobjThinker)
1495 && ((mobj_t *)currentthinker)->type == MT_SKULL)
1497 currentthinker = currentthinker->next;
1500 // if there are allready 20 skulls on the level,
1501 // don't spit another one
1506 // okay, there's playe for another one
1507 an = angle >> ANGLETOFINESHIFT;
1511 + 3*(actor->info->radius + mobjinfo[MT_SKULL].radius)/2;
1513 x = actor->x + FixedMul (prestep, finecosine[an]);
1514 y = actor->y + FixedMul (prestep, finesine[an]);
1515 z = actor->z + 8*FRACUNIT;
1517 newmobj = P_SpawnMobj (x , y, z, MT_SKULL);
1519 // Check for movements.
1520 if (!P_TryMove (newmobj, newmobj->x, newmobj->y))
1522 // kill it immediately
1523 P_DamageMobj (newmobj,actor,actor,10000);
1527 newmobj->target = actor->target;
1528 A_SkullAttack (newmobj, NULL);
1534 // Spawn a lost soul and launch it at the target
1536 void A_PainAttack (void *_actor, void*)
1538 mobj_t *actor = (mobj_t*)_actor;
1542 A_FaceTarget (actor, NULL);
1543 A_PainShootSkull (actor, actor->angle);
1547 void A_PainDie (void *_actor, void*)
1549 mobj_t *actor = (mobj_t*)_actor;
1550 A_Fall (actor, NULL);
1551 A_PainShootSkull (actor, actor->angle+ANG90);
1552 A_PainShootSkull (actor, actor->angle+ANG180);
1553 A_PainShootSkull (actor, actor->angle+ANG270);
1561 void A_Scream (void *_actor, void*)
1563 mobj_t *actor = (mobj_t*)_actor;
1566 switch (actor->info->deathsound)
1574 sound = sfx_podth1 + P_Random ()%3;
1579 sound = sfx_bgdth1 + P_Random ()%2;
1583 sound = actor->info->deathsound;
1587 // Check for bosses.
1588 if (actor->type==MT_SPIDER
1589 || actor->type == MT_CYBORG)
1592 S_StartSound (NULL, sound);
1595 S_StartSound (actor, sound);
1599 void A_XScream (void *_actor, void*)
1601 mobj_t *actor = (mobj_t*)_actor;
1602 S_StartSound (actor, sfx_slop);
1605 void A_Pain (void* _actor, void*)
1607 mobj_t *actor = (mobj_t*)_actor;
1608 if (actor->info->painsound)
1609 S_StartSound (actor, actor->info->painsound);
1614 void A_Fall (void *_actor, void*)
1616 mobj_t *actor = (mobj_t*)_actor;
1617 // actor is on ground, it can be walked over
1618 actor->flags &= ~MF_SOLID;
1620 // So change this if corpse objects
1621 // are meant to be obstacles.
1628 void A_Explode (void *_thingy, void*)
1630 mobj_t *thingy = (mobj_t*)_thingy;
1631 P_RadiusAttack ( thingy, thingy->target, 128 );
1637 // Possibly trigger special effects
1638 // if on first boss level
1640 void A_BossDeath (void *_mo, void*)
1642 mobj_t *mo = (mobj_t*)_mo;
1648 if ( gamemode == commercial)
1653 if ((mo->type != MT_FATSO)
1654 && (mo->type != MT_BABY))
1665 if (mo->type != MT_BRUISER)
1673 if (mo->type != MT_CYBORG)
1681 if (mo->type != MT_SPIDER)
1690 if (mo->type != MT_CYBORG)
1695 if (mo->type != MT_SPIDER)
1714 // make sure there is a player alive for victory
1715 for (i=0 ; i<MAXPLAYERS ; i++)
1716 if (playeringame[i] && players[i].health > 0)
1720 return; // no one left alive, so do not end game
1722 // scan the remaining thinkers to see
1723 // if all bosses are dead
1724 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
1726 if (th->function != P_MobjThinker)
1731 && mo2->type == mo->type
1734 // other boss not dead
1740 if ( gamemode == commercial)
1744 if (mo->type == MT_FATSO)
1747 EV_DoFloor(&junk,lowerFloorToLowest);
1751 if (mo->type == MT_BABY)
1754 EV_DoFloor(&junk,raiseToTexture);
1765 EV_DoFloor (&junk, lowerFloorToLowest);
1774 EV_DoDoor (&junk, BlazeOpen);
1780 EV_DoFloor (&junk, lowerFloorToLowest);
1791 void A_Hoof (void *_mo, void*)
1793 mobj_t *mo = (mobj_t*)_mo;
1794 S_StartSound (mo, sfx_hoof);
1798 void A_Metal (void *_mo, void*)
1800 mobj_t *mo = (mobj_t*)_mo;
1801 S_StartSound (mo, sfx_metal);
1805 void A_BabyMetal (void *_mo, void*)
1807 mobj_t *mo = (mobj_t*)_mo;
1808 S_StartSound (mo, sfx_bspwlk);
1813 A_OpenShotgun2(void *_player, void * /*psp*/)
1815 S_StartSound (((player_t*)_player)->mo, sfx_dbopn);
1819 A_LoadShotgun2(void *_player, void * /*psp*/)
1821 S_StartSound (((player_t*)_player)->mo, sfx_dbopn);
1824 void A_ReFire(void *player, void *psp);
1827 A_CloseShotgun2(void *_player, void *_psp)
1829 player_t *player = (player_t*)_player;
1830 pspdef_t *psp = (pspdef_t*)_psp;
1831 S_StartSound (player->mo, sfx_dbcls);
1832 A_ReFire(player,psp);
1837 mobj_t* braintargets[32];
1838 int numbraintargets;
1841 void A_BrainAwake (void * /*mo*/, void*)
1846 // find all the target spots
1847 numbraintargets = 0;
1850 for (thinker = thinkercap.next ;
1851 thinker != &thinkercap ;
1852 thinker = thinker->next)
1854 if (thinker->function != P_MobjThinker)
1855 continue; // not a mobj
1857 m = (mobj_t *)thinker;
1859 if (m->type == MT_BOSSTARGET )
1861 braintargets[numbraintargets] = m;
1866 S_StartSound (NULL,sfx_bossit);
1870 void A_BrainPain (void * /*mo*/, void*)
1872 S_StartSound (NULL,sfx_bospn);
1876 void A_BrainScream (void *_mo, void*)
1878 mobj_t *mo = (mobj_t*)_mo;
1884 for (x=mo->x - 196*FRACUNIT ; x< mo->x + 320*FRACUNIT ; x+= FRACUNIT*8)
1886 y = mo->y - 320*FRACUNIT;
1887 z = 128 + P_Random()*2*FRACUNIT;
1888 th = P_SpawnMobj (x,y,z, MT_ROCKET);
1889 th->momz = P_Random()*512;
1891 P_SetMobjState (th, S_BRAINEXPLODE1);
1893 th->tics -= P_Random()&7;
1898 S_StartSound (NULL,sfx_bosdth);
1903 void A_BrainExplode (void *_mo, void*)
1905 mobj_t *mo = (mobj_t*)_mo;
1911 x = mo->x + (P_Random () - P_Random ())*2048;
1913 z = 128 + P_Random()*2*FRACUNIT;
1914 th = P_SpawnMobj (x,y,z, MT_ROCKET);
1915 th->momz = P_Random()*512;
1917 P_SetMobjState (th, S_BRAINEXPLODE1);
1919 th->tics -= P_Random()&7;
1925 void A_BrainDie (void * /*mo*/, void*)
1930 void A_BrainSpit (void *_mo, void*)
1932 mobj_t *mo = (mobj_t*)_mo;
1936 static int easy = 0;
1939 if (gameskill <= sk_easy && (!easy))
1942 // shoot a cube at current target
1943 targ = braintargets[braintargeton];
1944 braintargeton = (braintargeton+1)%numbraintargets;
1946 // spawn brain missile
1947 newmobj = P_SpawnMissile (mo, targ, MT_SPAWNSHOT);
1948 newmobj->target = targ;
1949 newmobj->reactiontime =
1950 ((targ->y - mo->y)/newmobj->momy) / newmobj->state->tics;
1952 S_StartSound(NULL, sfx_bospit);
1957 void A_SpawnFly (void *_mo, void*);
1959 // travelling cube sound
1960 void A_SpawnSound (void *_mo, void*)
1962 mobj_t *mo = (mobj_t*)_mo;
1963 S_StartSound (mo,sfx_boscub);
1964 A_SpawnFly(mo, NULL);
1967 void A_SpawnFly (void *_mo, void*)
1969 mobj_t *mo = (mobj_t*)_mo;
1976 if (--mo->reactiontime)
1977 return; // still flying
1981 // First spawn teleport fog.
1982 fog = P_SpawnMobj (targ->x, targ->y, targ->z, MT_SPAWNFIRE);
1983 S_StartSound (fog, sfx_telept);
1985 // Randomly select monster to spawn.
1988 // Probability distribution (kind of :),
1989 // decreasing likelihood.
2013 newmobj = P_SpawnMobj (targ->x, targ->y, targ->z, type);
2014 if (P_LookForPlayers (newmobj, true) )
2015 P_SetMobjState (newmobj, newmobj->info->seestate);
2017 // telefrag anything in this spot
2018 P_TeleportMove (newmobj, newmobj->x, newmobj->y);
2020 // remove self (i.e., cube).
2026 void A_PlayerScream (void *_mo, void*)
2028 mobj_t *mo = (mobj_t*)_mo;
2029 // Default death sound.
2030 int sound = sfx_pldeth;
2032 if ( (gamemode == commercial)
2033 && (mo->health < -50))
2035 // IF THE PLAYER DIES
2036 // LESS THAN -50% WITHOUT GIBBING
2040 S_StartSound (mo, sound);