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
18 // Revision 1.3 2004/04/28 10:17:39 hkiel
19 // For consistency use __AMIGAOS__ instead of AMIGAOS and enable Xaos again
21 // Revision 1.2 2004/04/27 16:42:56 hkiel
22 // Fixed #ifdef AMIGA to #ifdef AMIGAOS
24 // Revision 1.1 2000/02/29 18:21:04 stegerg
25 // Doom port based on ADoomPPC. Read README.AROS!
29 // Enemy thinking, AI.
30 // Action Pointer Functions
31 // that are associated with states/frames.
33 //-----------------------------------------------------------------------------
84 // P_NewChaseDir related LUT.
86 dirtype_t opposite
[] =
88 DI_WEST
, DI_SOUTHWEST
, DI_SOUTH
, DI_SOUTHEAST
,
89 DI_EAST
, DI_NORTHEAST
, DI_NORTH
, DI_NORTHWEST
, DI_NODIR
94 DI_NORTHWEST
, DI_NORTHEAST
, DI_SOUTHWEST
, DI_SOUTHEAST
101 void A_Fall (mobj_t
*actor
);
106 // Enemies are allways spawned
107 // with targetplayer = -1, threshold = 0
108 // Most monsters are spawned unaware of all players,
109 // but some can be made preaware
114 // Called by P_NoiseAlert.
115 // Recursively traverse adjacent sectors,
116 // sound blocking lines cut off traversal.
130 // wake up all monsters in this sector
131 if (sec
->validcount
== validcount
132 && sec
->soundtraversed
<= soundblocks
+1)
134 return; // already flooded
137 sec
->validcount
= validcount
;
138 sec
->soundtraversed
= soundblocks
+1;
139 sec
->soundtarget
= soundtarget
;
141 for (i
=0 ;i
<sec
->linecount
; i
++)
143 check
= sec
->lines
[i
];
144 if (! (check
->flags
& ML_TWOSIDED
) )
147 P_LineOpening (check
);
150 continue; // closed door
152 if ( sides
[ check
->sidenum
[0] ].sector
== sec
)
153 other
= sides
[ check
->sidenum
[1] ] .sector
;
155 other
= sides
[ check
->sidenum
[0] ].sector
;
157 if (check
->flags
& ML_SOUNDBLOCK
)
160 P_RecursiveSound (other
, 1);
163 P_RecursiveSound (other
, soundblocks
);
171 // If a monster yells at a player,
172 // it will alert other monsters to the player.
179 soundtarget
= target
;
181 P_RecursiveSound (emmiter
->subsector
->sector
, 0);
190 boolean
P_CheckMeleeRange (mobj_t
* actor
)
199 dist
= P_AproxDistance (pl
->x
-actor
->x
, pl
->y
-actor
->y
);
201 if (dist
>= MELEERANGE
-20*FRACUNIT
+pl
->info
->radius
)
204 if (! P_CheckSight (actor
, actor
->target
) )
211 // P_CheckMissileRange
213 boolean
P_CheckMissileRange (mobj_t
* actor
)
217 if (! P_CheckSight (actor
, actor
->target
) )
220 if ( actor
->flags
& MF_JUSTHIT
)
222 // the target just hit the enemy,
224 actor
->flags
&= ~MF_JUSTHIT
;
228 if (actor
->reactiontime
)
229 return false; // do not attack yet
231 // OPTIMIZE: get this from a global checksight
232 dist
= P_AproxDistance ( actor
->x
-actor
->target
->x
,
233 actor
->y
-actor
->target
->y
) - 64*FRACUNIT
;
235 if (!actor
->info
->meleestate
)
236 dist
-= 128*FRACUNIT
; // no melee attack, so fire more
240 if (actor
->type
== MT_VILE
)
243 return false; // too far away
247 if (actor
->type
== MT_UNDEAD
)
250 return false; // close for fist attack
255 if (actor
->type
== MT_CYBORG
256 || actor
->type
== MT_SPIDER
257 || actor
->type
== MT_SKULL
)
265 if (actor
->type
== MT_CYBORG
&& dist
> 160)
268 if (P_Random () < dist
)
277 // Move in the current direction,
278 // returns false if the move is blocked.
280 fixed_t xspeed
[8] = {FRACUNIT
,47000,0,-47000,-FRACUNIT
,-47000,0,47000};
281 fixed_t yspeed
[8] = {0,47000,FRACUNIT
,47000,0,-47000,-FRACUNIT
,-47000};
283 #define MAXSPECIALCROSS 20 /* was 8 */
285 extern line_t
* spechit
[MAXSPECIALCROSS
];
286 extern int numspechit
;
288 boolean
P_Move (mobj_t
* actor
)
295 // warning: 'catch', 'throw', and 'try'
296 // are all C++ reserved words
300 if (actor
->movedir
== DI_NODIR
)
303 if ((unsigned)actor
->movedir
>= 8)
304 I_Error ("Weird actor->movedir!");
306 tryx
= actor
->x
+ actor
->info
->speed
*xspeed
[actor
->movedir
];
307 tryy
= actor
->y
+ actor
->info
->speed
*yspeed
[actor
->movedir
];
309 try_ok
= P_TryMove (actor
, tryx
, tryy
);
314 if (actor
->flags
& MF_FLOAT
&& floatok
)
316 // must adjust height
317 if (actor
->z
< tmfloorz
)
318 actor
->z
+= FLOATSPEED
;
320 actor
->z
-= FLOATSPEED
;
322 actor
->flags
|= MF_INFLOAT
;
329 actor
->movedir
= DI_NODIR
;
333 ld
= spechit
[numspechit
];
334 // if the special is not a door
335 // that can be opened,
337 if (P_UseSpecialLine (actor
, ld
,0))
344 actor
->flags
&= ~MF_INFLOAT
;
348 if (! (actor
->flags
& MF_FLOAT
) )
349 actor
->z
= actor
->floorz
;
356 // Attempts to move actor on
357 // in its current (ob->moveangle) direction.
358 // If blocked by either a wall or an actor
360 // If move is either clear or blocked only by a door,
361 // returns TRUE and sets...
362 // If a door is in the way,
363 // an OpenDoor call is made to start it opening.
365 boolean
P_TryWalk (mobj_t
* actor
)
372 actor
->movecount
= P_Random()&15;
379 void P_NewChaseDir (mobj_t
* actor
)
389 dirtype_t turnaround
;
392 I_Error ("P_NewChaseDir: called with no target");
394 olddir
= actor
->movedir
;
395 turnaround
=opposite
[olddir
];
397 deltax
= actor
->target
->x
- actor
->x
;
398 deltay
= actor
->target
->y
- actor
->y
;
400 if (deltax
>10*FRACUNIT
)
402 else if (deltax
<-10*FRACUNIT
)
407 if (deltay
<-10*FRACUNIT
)
409 else if (deltay
>10*FRACUNIT
)
418 actor
->movedir
= diags
[((deltay
<0)<<1)+(deltax
>0)];
419 if (actor
->movedir
!= turnaround
&& P_TryWalk(actor
))
423 // try other directions
425 || iabs(deltay
)>iabs(deltax
))
432 if (d
[1]==turnaround
)
434 if (d
[2]==turnaround
)
439 actor
->movedir
= d
[1];
440 if (P_TryWalk(actor
))
442 // either moved forward or attacked
449 actor
->movedir
=d
[2];
451 if (P_TryWalk(actor
))
455 // there is no direct path to the player,
456 // so pick another direction.
457 if (olddir
!=DI_NODIR
)
459 actor
->movedir
=olddir
;
461 if (P_TryWalk(actor
))
465 // randomly determine direction of search
472 if (tdir
!=turnaround
)
474 actor
->movedir
=tdir
;
476 if ( P_TryWalk(actor
) )
483 for ( tdir
=DI_SOUTHEAST
;
487 if (tdir
!=turnaround
)
489 actor
->movedir
=tdir
;
491 if ( P_TryWalk(actor
) )
497 if (turnaround
!= DI_NODIR
)
499 actor
->movedir
=turnaround
;
500 if ( P_TryWalk(actor
) )
504 actor
->movedir
= DI_NODIR
; // can not move
511 // If allaround is false, only look 180 degrees in front.
512 // Returns true if a player is targeted.
526 sector
= actor
->subsector
->sector
;
529 stop
= (actor
->lastlook
-1)&3;
531 for ( ; ; actor
->lastlook
= (actor
->lastlook
+1)&3 )
533 if (!playeringame
[actor
->lastlook
]) {
541 || actor
->lastlook
== stop
)
547 player
= &players
[actor
->lastlook
];
549 if (player
->health
<= 0)
552 if (!P_CheckSight (actor
, player
->mo
))
553 continue; // out of sight
557 an
= R_PointToAngle2 (actor
->x
,
563 if (an
> ANG90
&& an
< ANG270
)
565 dist
= P_AproxDistance (player
->mo
->x
- actor
->x
,
566 player
->mo
->y
- actor
->y
);
567 // if real close, react anyway
568 if (dist
> MELEERANGE
)
569 continue; // behind back
573 actor
->target
= player
->mo
;
583 // DOOM II special, map 32.
584 // Uses special tag 666.
586 void A_KeenDie (mobj_t
* mo
)
594 // scan the remaining thinkers
595 // to see if all Keens are dead
596 for (th
= thinkercap
.next
; th
!= &thinkercap
; th
=th
->next
)
598 if (th
->function
.acp1
!= (actionf_p1
)P_MobjThinker
)
603 && mo2
->type
== mo
->type
606 // other Keen not dead
612 EV_DoDoor(&junk
,open
);
622 // Stay in state until a player is sighted.
624 void A_Look (mobj_t
* actor
)
628 actor
->threshold
= 0; // any shot will wake up
629 targ
= actor
->subsector
->sector
->soundtarget
;
632 && (targ
->flags
& MF_SHOOTABLE
) )
634 actor
->target
= targ
;
636 if ( actor
->flags
& MF_AMBUSH
)
638 if (P_CheckSight (actor
, actor
->target
))
646 if (!P_LookForPlayers (actor
, false) )
649 // go into chase state
651 if (actor
->info
->seesound
)
655 switch (actor
->info
->seesound
)
660 sound
= sfx_posit1
+P_Random()%3;
665 sound
= sfx_bgsit1
+P_Random()%2;
669 sound
= actor
->info
->seesound
;
673 if (actor
->type
==MT_SPIDER
674 || actor
->type
== MT_CYBORG
)
677 S_StartSound (NULL
, sound
);
680 S_StartSound (actor
, sound
);
683 P_SetMobjState (actor
, actor
->info
->seestate
);
689 // Actor has a melee attack,
690 // so it tries to close as fast as possible
692 void A_Chase (mobj_t
* actor
)
696 if (actor
->reactiontime
)
697 actor
->reactiontime
--;
700 // modify target threshold
701 if (actor
->threshold
)
704 || actor
->target
->health
<= 0)
706 actor
->threshold
= 0;
712 // turn towards movement direction if not there yet
713 if (actor
->movedir
< 8)
715 actor
->angle
&= (7<<29);
716 delta
= actor
->angle
- (actor
->movedir
<< 29);
719 actor
->angle
-= ANG90
/2;
721 actor
->angle
+= ANG90
/2;
725 || !(actor
->target
->flags
&MF_SHOOTABLE
))
727 // look for a new target
728 if (P_LookForPlayers(actor
,true))
729 return; // got a new target
731 P_SetMobjState (actor
, actor
->info
->spawnstate
);
735 // do not attack twice in a row
736 if (actor
->flags
& MF_JUSTATTACKED
)
738 actor
->flags
&= ~MF_JUSTATTACKED
;
739 if (gameskill
!= sk_nightmare
&& !fastparm
)
740 P_NewChaseDir (actor
);
744 // check for melee attack
745 if (actor
->info
->meleestate
746 && P_CheckMeleeRange (actor
))
748 if (actor
->info
->attacksound
)
749 S_StartSound (actor
, actor
->info
->attacksound
);
751 P_SetMobjState (actor
, actor
->info
->meleestate
);
755 // check for missile attack
756 if (actor
->info
->missilestate
)
758 if (gameskill
< sk_nightmare
759 && !fastparm
&& actor
->movecount
)
764 if (!P_CheckMissileRange (actor
))
767 P_SetMobjState (actor
, actor
->info
->missilestate
);
768 actor
->flags
|= MF_JUSTATTACKED
;
774 // possibly choose another target
777 && !P_CheckSight (actor
, actor
->target
) )
779 if (P_LookForPlayers(actor
,true))
780 return; // got a new target
783 // chase towards player
784 if (--actor
->movecount
<0
787 P_NewChaseDir (actor
);
791 if (actor
->info
->activesound
794 S_StartSound (actor
, actor
->info
->activesound
);
802 void A_FaceTarget (mobj_t
* actor
)
807 actor
->flags
&= ~MF_AMBUSH
;
809 actor
->angle
= R_PointToAngle2 (actor
->x
,
814 if (actor
->target
->flags
& MF_SHADOW
)
815 actor
->angle
+= (P_Random()-P_Random())<<21;
822 void A_PosAttack (mobj_t
* actor
)
831 A_FaceTarget (actor
);
832 angle
= actor
->angle
;
833 slope
= P_AimLineAttack (actor
, angle
, MISSILERANGE
);
835 S_StartSound (actor
, sfx_pistol
);
836 angle
+= (P_Random()-P_Random())<<20;
837 damage
= ((P_Random()%5)+1)*3;
838 P_LineAttack (actor
, angle
, MISSILERANGE
, slope
, damage
);
841 void A_SPosAttack (mobj_t
* actor
)
852 S_StartSound (actor
, sfx_shotgn
);
853 A_FaceTarget (actor
);
854 bangle
= actor
->angle
;
855 slope
= P_AimLineAttack (actor
, bangle
, MISSILERANGE
);
857 for (i
=0 ; i
<3 ; i
++)
859 angle
= bangle
+ ((P_Random()-P_Random())<<20);
860 damage
= ((P_Random()%5)+1)*3;
861 P_LineAttack (actor
, angle
, MISSILERANGE
, slope
, damage
);
865 void A_CPosAttack (mobj_t
* actor
)
875 S_StartSound (actor
, sfx_shotgn
);
876 A_FaceTarget (actor
);
877 bangle
= actor
->angle
;
878 slope
= P_AimLineAttack (actor
, bangle
, MISSILERANGE
);
880 angle
= bangle
+ ((P_Random()-P_Random())<<20);
881 damage
= ((P_Random()%5)+1)*3;
882 P_LineAttack (actor
, angle
, MISSILERANGE
, slope
, damage
);
885 void A_CPosRefire (mobj_t
* actor
)
887 // keep firing unless target got out of sight
888 A_FaceTarget (actor
);
890 if (P_Random () < 40)
894 || actor
->target
->health
<= 0
895 || !P_CheckSight (actor
, actor
->target
) )
897 P_SetMobjState (actor
, actor
->info
->seestate
);
902 void A_SpidRefire (mobj_t
* actor
)
904 // keep firing unless target got out of sight
905 A_FaceTarget (actor
);
907 if (P_Random () < 10)
911 || actor
->target
->health
<= 0
912 || !P_CheckSight (actor
, actor
->target
) )
914 P_SetMobjState (actor
, actor
->info
->seestate
);
918 void A_BspiAttack (mobj_t
*actor
)
923 A_FaceTarget (actor
);
926 P_SpawnMissile (actor
, actor
->target
, MT_ARACHPLAZ
);
933 void A_TroopAttack (mobj_t
* actor
)
940 A_FaceTarget (actor
);
941 if (P_CheckMeleeRange (actor
))
943 S_StartSound (actor
, sfx_claw
);
944 damage
= (P_Random()%8+1)*3;
945 P_DamageMobj (actor
->target
, actor
, actor
, damage
);
951 P_SpawnMissile (actor
, actor
->target
, MT_TROOPSHOT
);
955 void A_SargAttack (mobj_t
* actor
)
962 A_FaceTarget (actor
);
963 if (P_CheckMeleeRange (actor
))
965 damage
= ((P_Random()%10)+1)*4;
966 P_DamageMobj (actor
->target
, actor
, actor
, damage
);
970 void A_HeadAttack (mobj_t
* actor
)
977 A_FaceTarget (actor
);
978 if (P_CheckMeleeRange (actor
))
980 damage
= (P_Random()%6+1)*10;
981 P_DamageMobj (actor
->target
, actor
, actor
, damage
);
986 P_SpawnMissile (actor
, actor
->target
, MT_HEADSHOT
);
989 void A_CyberAttack (mobj_t
* actor
)
994 A_FaceTarget (actor
);
995 P_SpawnMissile (actor
, actor
->target
, MT_ROCKET
);
999 void A_BruisAttack (mobj_t
* actor
)
1006 if (P_CheckMeleeRange (actor
))
1008 S_StartSound (actor
, sfx_claw
);
1009 damage
= (P_Random()%8+1)*10;
1010 P_DamageMobj (actor
->target
, actor
, actor
, damage
);
1015 P_SpawnMissile (actor
, actor
->target
, MT_BRUISERSHOT
);
1022 void A_SkelMissile (mobj_t
* actor
)
1029 A_FaceTarget (actor
);
1030 actor
->z
+= 16*FRACUNIT
; // so missile spawns higher
1031 mo
= P_SpawnMissile (actor
, actor
->target
, MT_TRACER
);
1032 actor
->z
-= 16*FRACUNIT
; // back to normal
1036 mo
->tracer
= actor
->target
;
1039 int TRACEANGLE
= 0xc000000;
1041 void A_Tracer (mobj_t
* actor
)
1052 // spawn a puff of smoke behind the rocket
1053 P_SpawnPuff (actor
->x
, actor
->y
, actor
->z
);
1055 th
= P_SpawnMobj (actor
->x
-actor
->momx
,
1056 actor
->y
-actor
->momy
,
1057 actor
->z
, MT_SMOKE
);
1059 th
->momz
= FRACUNIT
;
1060 th
->tics
-= P_Random()&3;
1065 dest
= actor
->tracer
;
1067 if (!dest
|| dest
->health
<= 0)
1071 exact
= R_PointToAngle2 (actor
->x
,
1076 if (exact
!= actor
->angle
)
1078 if (exact
- actor
->angle
> 0x80000000)
1080 actor
->angle
-= TRACEANGLE
;
1081 if (exact
- actor
->angle
< 0x80000000)
1082 actor
->angle
= exact
;
1086 actor
->angle
+= TRACEANGLE
;
1087 if (exact
- actor
->angle
> 0x80000000)
1088 actor
->angle
= exact
;
1092 exact
= actor
->angle
>>ANGLETOFINESHIFT
;
1093 actor
->momx
= FixedMul (actor
->info
->speed
, finecosine
[exact
]);
1094 actor
->momy
= FixedMul (actor
->info
->speed
, finesine
[exact
]);
1097 dist
= P_AproxDistance (dest
->x
- actor
->x
,
1098 dest
->y
- actor
->y
);
1100 dist
= dist
/ actor
->info
->speed
;
1104 slope
= (dest
->z
+40*FRACUNIT
- actor
->z
) / dist
;
1106 if (slope
< actor
->momz
)
1107 actor
->momz
-= FRACUNIT
/8;
1109 actor
->momz
+= FRACUNIT
/8;
1113 void A_SkelWhoosh (mobj_t
* actor
)
1117 A_FaceTarget (actor
);
1118 S_StartSound (actor
,sfx_skeswg
);
1121 void A_SkelFist (mobj_t
* actor
)
1128 A_FaceTarget (actor
);
1130 if (P_CheckMeleeRange (actor
))
1132 damage
= ((P_Random()%10)+1)*6;
1133 S_StartSound (actor
, sfx_skepch
);
1134 P_DamageMobj (actor
->target
, actor
, actor
, damage
);
1142 // Detect a corpse that could be raised.
1149 boolean
PIT_VileCheck (mobj_t
* thing
)
1154 if (!(thing
->flags
& MF_CORPSE
) )
1155 return true; // not a monster
1157 if (thing
->tics
!= -1)
1158 return true; // not lying still yet
1160 if (thing
->info
->raisestate
== S_NULL
)
1161 return true; // monster doesn't have a raise state
1163 maxdist
= thing
->info
->radius
+ mobjinfo
[MT_VILE
].radius
;
1165 if ( iabs(thing
->x
- viletryx
) > maxdist
1166 || iabs(thing
->y
- viletryy
) > maxdist
)
1167 return true; // not actually touching
1170 corpsehit
->momx
= corpsehit
->momy
= 0;
1171 corpsehit
->height
<<= 2;
1172 check
= P_CheckPosition (corpsehit
, corpsehit
->x
, corpsehit
->y
);
1173 corpsehit
->height
>>= 2;
1176 return true; // doesn't fit here
1178 return false; // got one, so stop checking
1185 // Check for ressurecting a body
1187 void A_VileChase (mobj_t
* actor
)
1200 if (actor
->movedir
!= DI_NODIR
)
1202 // check for corpses to raise
1204 actor
->x
+ actor
->info
->speed
*xspeed
[actor
->movedir
];
1206 actor
->y
+ actor
->info
->speed
*yspeed
[actor
->movedir
];
1208 xl
= (viletryx
- bmaporgx
- MAXRADIUS
*2)>>MAPBLOCKSHIFT
;
1209 xh
= (viletryx
- bmaporgx
+ MAXRADIUS
*2)>>MAPBLOCKSHIFT
;
1210 yl
= (viletryy
- bmaporgy
- MAXRADIUS
*2)>>MAPBLOCKSHIFT
;
1211 yh
= (viletryy
- bmaporgy
+ MAXRADIUS
*2)>>MAPBLOCKSHIFT
;
1214 for (bx
=xl
; bx
<=xh
; bx
++)
1216 for (by
=yl
; by
<=yh
; by
++)
1218 // Call PIT_VileCheck to check
1219 // whether object is a corpse
1220 // that canbe raised.
1221 if (!P_BlockThingsIterator(bx
,by
,PIT_VileCheck
))
1224 temp
= actor
->target
;
1225 actor
->target
= corpsehit
;
1226 A_FaceTarget (actor
);
1227 actor
->target
= temp
;
1229 P_SetMobjState (actor
, S_VILE_HEAL1
);
1230 S_StartSound (corpsehit
, sfx_slop
);
1231 info
= corpsehit
->info
;
1233 P_SetMobjState (corpsehit
,info
->raisestate
);
1234 corpsehit
->height
<<= 2;
1235 corpsehit
->flags
= info
->flags
;
1236 corpsehit
->health
= info
->spawnhealth
;
1237 corpsehit
->target
= NULL
;
1245 // Return to normal attack.
1253 void A_VileStart (mobj_t
* actor
)
1255 S_StartSound (actor
, sfx_vilatk
);
1261 // Keep fire in front of player unless out of sight
1263 void A_Fire (mobj_t
* actor
);
1265 void A_StartFire (mobj_t
* actor
)
1267 S_StartSound(actor
,sfx_flamst
);
1271 void A_FireCrackle (mobj_t
* actor
)
1273 S_StartSound(actor
,sfx_flame
);
1277 void A_Fire (mobj_t
* actor
)
1282 dest
= actor
->tracer
;
1286 // don't move it if the vile lost sight
1287 if (!P_CheckSight (actor
->target
, dest
) )
1290 an
= dest
->angle
>> ANGLETOFINESHIFT
;
1292 P_UnsetThingPosition (actor
);
1293 actor
->x
= dest
->x
+ FixedMul (24*FRACUNIT
, finecosine
[an
]);
1294 actor
->y
= dest
->y
+ FixedMul (24*FRACUNIT
, finesine
[an
]);
1296 P_SetThingPosition (actor
);
1303 // Spawn the hellfire
1305 void A_VileTarget (mobj_t
* actor
)
1312 A_FaceTarget (actor
);
1314 fog
= P_SpawnMobj (actor
->target
->x
,
1316 actor
->target
->z
, MT_FIRE
);
1318 actor
->tracer
= fog
;
1319 fog
->target
= actor
;
1320 fog
->tracer
= actor
->target
;
1330 void A_VileAttack (mobj_t
* actor
)
1338 A_FaceTarget (actor
);
1340 if (!P_CheckSight (actor
, actor
->target
) )
1343 S_StartSound (actor
, sfx_barexp
);
1344 P_DamageMobj (actor
->target
, actor
, actor
, 20);
1345 actor
->target
->momz
= 1000*FRACUNIT
/actor
->target
->info
->mass
;
1347 an
= actor
->angle
>> ANGLETOFINESHIFT
;
1349 fire
= actor
->tracer
;
1354 // move the fire between the vile and the player
1355 fire
->x
= actor
->target
->x
- FixedMul (24*FRACUNIT
, finecosine
[an
]);
1356 fire
->y
= actor
->target
->y
- FixedMul (24*FRACUNIT
, finesine
[an
]);
1357 P_RadiusAttack (fire
, actor
, 70 );
1365 // firing three missiles (bruisers)
1366 // in three different directions?
1367 // Doesn't look like it.
1369 #define FATSPREAD (ANG90/8)
1371 void A_FatRaise (mobj_t
*actor
)
1373 A_FaceTarget (actor
);
1374 S_StartSound (actor
, sfx_manatk
);
1378 void A_FatAttack1 (mobj_t
* actor
)
1383 A_FaceTarget (actor
);
1384 // Change direction to ...
1385 actor
->angle
+= FATSPREAD
;
1386 P_SpawnMissile (actor
, actor
->target
, MT_FATSHOT
);
1388 mo
= P_SpawnMissile (actor
, actor
->target
, MT_FATSHOT
);
1389 mo
->angle
+= FATSPREAD
;
1390 an
= mo
->angle
>> ANGLETOFINESHIFT
;
1391 mo
->momx
= FixedMul (mo
->info
->speed
, finecosine
[an
]);
1392 mo
->momy
= FixedMul (mo
->info
->speed
, finesine
[an
]);
1395 void A_FatAttack2 (mobj_t
* actor
)
1400 A_FaceTarget (actor
);
1401 // Now here choose opposite deviation.
1402 actor
->angle
-= FATSPREAD
;
1403 P_SpawnMissile (actor
, actor
->target
, MT_FATSHOT
);
1405 mo
= P_SpawnMissile (actor
, actor
->target
, MT_FATSHOT
);
1406 mo
->angle
-= FATSPREAD
*2;
1407 an
= mo
->angle
>> ANGLETOFINESHIFT
;
1408 mo
->momx
= FixedMul (mo
->info
->speed
, finecosine
[an
]);
1409 mo
->momy
= FixedMul (mo
->info
->speed
, finesine
[an
]);
1412 void A_FatAttack3 (mobj_t
* actor
)
1417 A_FaceTarget (actor
);
1419 mo
= P_SpawnMissile (actor
, actor
->target
, MT_FATSHOT
);
1420 mo
->angle
-= FATSPREAD
/2;
1421 an
= mo
->angle
>> ANGLETOFINESHIFT
;
1422 mo
->momx
= FixedMul (mo
->info
->speed
, finecosine
[an
]);
1423 mo
->momy
= FixedMul (mo
->info
->speed
, finesine
[an
]);
1425 mo
= P_SpawnMissile (actor
, actor
->target
, MT_FATSHOT
);
1426 mo
->angle
+= FATSPREAD
/2;
1427 an
= mo
->angle
>> ANGLETOFINESHIFT
;
1428 mo
->momx
= FixedMul (mo
->info
->speed
, finecosine
[an
]);
1429 mo
->momy
= FixedMul (mo
->info
->speed
, finesine
[an
]);
1435 // Fly at the player like a missile.
1437 #define SKULLSPEED (20*FRACUNIT)
1439 void A_SkullAttack (mobj_t
* actor
)
1448 dest
= actor
->target
;
1449 actor
->flags
|= MF_SKULLFLY
;
1451 S_StartSound (actor
, actor
->info
->attacksound
);
1452 A_FaceTarget (actor
);
1453 an
= actor
->angle
>> ANGLETOFINESHIFT
;
1454 actor
->momx
= FixedMul (SKULLSPEED
, finecosine
[an
]);
1455 actor
->momy
= FixedMul (SKULLSPEED
, finesine
[an
]);
1456 dist
= P_AproxDistance (dest
->x
- actor
->x
, dest
->y
- actor
->y
);
1457 dist
= dist
/ SKULLSPEED
;
1461 actor
->momz
= (dest
->z
+(dest
->height
>>1) - actor
->z
) / dist
;
1467 // Spawn a lost soul and launch it at the target
1482 thinker_t
* currentthinker
;
1484 // count total number of skull currently on the level
1487 currentthinker
= thinkercap
.next
;
1488 while (currentthinker
!= &thinkercap
)
1490 if ( (currentthinker
->function
.acp1
== (actionf_p1
)P_MobjThinker
)
1491 && ((mobj_t
*)currentthinker
)->type
== MT_SKULL
)
1493 currentthinker
= currentthinker
->next
;
1496 // if there are allready 20 skulls on the level,
1497 // don't spit another one
1502 // okay, there's playe for another one
1503 an
= angle
>> ANGLETOFINESHIFT
;
1507 + 3*(actor
->info
->radius
+ mobjinfo
[MT_SKULL
].radius
)/2;
1509 x
= actor
->x
+ FixedMul (prestep
, finecosine
[an
]);
1510 y
= actor
->y
+ FixedMul (prestep
, finesine
[an
]);
1511 z
= actor
->z
+ 8*FRACUNIT
;
1513 newmobj
= P_SpawnMobj (x
, y
, z
, MT_SKULL
);
1515 // Check for movements.
1516 if (!P_TryMove (newmobj
, newmobj
->x
, newmobj
->y
))
1518 // kill it immediately
1519 P_DamageMobj (newmobj
,actor
,actor
,10000);
1523 newmobj
->target
= actor
->target
;
1524 A_SkullAttack (newmobj
);
1530 // Spawn a lost soul and launch it at the target
1532 void A_PainAttack (mobj_t
* actor
)
1537 A_FaceTarget (actor
);
1538 A_PainShootSkull (actor
, actor
->angle
);
1542 void A_PainDie (mobj_t
* actor
)
1545 A_PainShootSkull (actor
, actor
->angle
+ANG90
);
1546 A_PainShootSkull (actor
, actor
->angle
+ANG180
);
1547 A_PainShootSkull (actor
, actor
->angle
+ANG270
);
1555 void A_Scream (mobj_t
* actor
)
1559 switch (actor
->info
->deathsound
)
1567 sound
= sfx_podth1
+ P_Random ()%3;
1572 sound
= sfx_bgdth1
+ P_Random ()%2;
1576 sound
= actor
->info
->deathsound
;
1580 // Check for bosses.
1581 if (actor
->type
==MT_SPIDER
1582 || actor
->type
== MT_CYBORG
)
1585 S_StartSound (NULL
, sound
);
1588 S_StartSound (actor
, sound
);
1592 void A_XScream (mobj_t
* actor
)
1594 S_StartSound (actor
, sfx_slop
);
1597 void A_Pain (mobj_t
* actor
)
1599 if (actor
->info
->painsound
)
1600 S_StartSound (actor
, actor
->info
->painsound
);
1605 void A_Fall (mobj_t
*actor
)
1607 // actor is on ground, it can be walked over
1608 actor
->flags
&= ~MF_SOLID
;
1610 // So change this if corpse objects
1611 // are meant to be obstacles.
1618 void A_Explode (mobj_t
* thingy
)
1620 P_RadiusAttack ( thingy
, thingy
->target
, 128 );
1626 // Possibly trigger special effects
1627 // if on first boss level
1629 void A_BossDeath (mobj_t
* mo
)
1636 if ( gamemode
== commercial
)
1641 if ((mo
->type
!= MT_FATSO
)
1642 && (mo
->type
!= MT_BABY
))
1653 if (mo
->type
!= MT_BRUISER
)
1661 if (mo
->type
!= MT_CYBORG
)
1669 if (mo
->type
!= MT_SPIDER
)
1678 if (mo
->type
!= MT_CYBORG
)
1683 if (mo
->type
!= MT_SPIDER
)
1702 // make sure there is a player alive for victory
1703 for (i
=0 ; i
<MAXPLAYERS
; i
++)
1704 if (playeringame
[i
] && players
[i
].health
> 0)
1708 return; // no one left alive, so do not end game
1710 // scan the remaining thinkers to see
1711 // if all bosses are dead
1712 for (th
= thinkercap
.next
; th
!= &thinkercap
; th
=th
->next
)
1714 if (th
->function
.acp1
!= (actionf_p1
)P_MobjThinker
)
1719 && mo2
->type
== mo
->type
1722 // other boss not dead
1728 if ( gamemode
== commercial
)
1732 if (mo
->type
== MT_FATSO
)
1735 EV_DoFloor(&junk
,lowerFloorToLowest
);
1739 if (mo
->type
== MT_BABY
)
1742 EV_DoFloor(&junk
,raiseToTexture
);
1753 EV_DoFloor (&junk
, lowerFloorToLowest
);
1762 EV_DoDoor (&junk
, blazeOpen
);
1768 EV_DoFloor (&junk
, lowerFloorToLowest
);
1779 void A_Hoof (mobj_t
* mo
)
1781 S_StartSound (mo
, sfx_hoof
);
1785 void A_Metal (mobj_t
* mo
)
1787 S_StartSound (mo
, sfx_metal
);
1791 void A_BabyMetal (mobj_t
* mo
)
1793 S_StartSound (mo
, sfx_bspwlk
);
1802 S_StartSound (player
->mo
, sfx_dbopn
);
1810 S_StartSound (player
->mo
, sfx_dbload
);
1823 S_StartSound (player
->mo
, sfx_dbcls
);
1824 A_ReFire(player
,psp
);
1829 mobj_t
* braintargets
[32];
1830 int numbraintargets
;
1833 void A_BrainAwake (mobj_t
* mo
)
1838 // find all the target spots
1839 numbraintargets
= 0;
1842 thinker
= thinkercap
.next
;
1843 for (thinker
= thinkercap
.next
;
1844 thinker
!= &thinkercap
;
1845 thinker
= thinker
->next
)
1847 if (thinker
->function
.acp1
!= (actionf_p1
)P_MobjThinker
)
1848 continue; // not a mobj
1850 m
= (mobj_t
*)thinker
;
1852 if (m
->type
== MT_BOSSTARGET
)
1854 braintargets
[numbraintargets
] = m
;
1859 S_StartSound (NULL
,sfx_bossit
);
1863 void A_BrainPain (mobj_t
* mo
)
1865 S_StartSound (NULL
,sfx_bospn
);
1869 void A_BrainScream (mobj_t
* mo
)
1876 for (x
=mo
->x
- 196*FRACUNIT
; x
< mo
->x
+ 320*FRACUNIT
; x
+= FRACUNIT
*8)
1878 y
= mo
->y
- 320*FRACUNIT
;
1879 z
= 128 + P_Random()*2*FRACUNIT
;
1880 th
= P_SpawnMobj (x
,y
,z
, MT_ROCKET
);
1881 th
->momz
= P_Random()*512;
1883 P_SetMobjState (th
, S_BRAINEXPLODE1
);
1885 th
->tics
-= P_Random()&7;
1890 S_StartSound (NULL
,sfx_bosdth
);
1895 void A_BrainExplode (mobj_t
* mo
)
1902 x
= mo
->x
+ (P_Random () - P_Random ())*2048;
1904 z
= 128 + P_Random()*2*FRACUNIT
;
1905 th
= P_SpawnMobj (x
,y
,z
, MT_ROCKET
);
1906 th
->momz
= P_Random()*512;
1908 P_SetMobjState (th
, S_BRAINEXPLODE1
);
1910 th
->tics
-= P_Random()&7;
1916 void A_BrainDie (mobj_t
* mo
)
1921 void A_BrainSpit (mobj_t
* mo
)
1926 static int easy
= 0;
1929 if (gameskill
<= sk_easy
&& (!easy
))
1932 // shoot a cube at current target
1933 targ
= braintargets
[braintargeton
];
1934 braintargeton
= (braintargeton
+1)%numbraintargets
;
1936 // spawn brain missile
1937 newmobj
= P_SpawnMissile (mo
, targ
, MT_SPAWNSHOT
);
1938 newmobj
->target
= targ
;
1939 newmobj
->reactiontime
=
1940 ((targ
->y
- mo
->y
)/newmobj
->momy
) / newmobj
->state
->tics
;
1942 S_StartSound(NULL
, sfx_bospit
);
1947 void A_SpawnFly (mobj_t
* mo
);
1949 // travelling cube sound
1950 void A_SpawnSound (mobj_t
* mo
)
1952 S_StartSound (mo
,sfx_boscub
);
1956 void A_SpawnFly (mobj_t
* mo
)
1964 if (--mo
->reactiontime
)
1965 return; // still flying
1969 // First spawn teleport fog.
1970 fog
= P_SpawnMobj (targ
->x
, targ
->y
, targ
->z
, MT_SPAWNFIRE
);
1971 S_StartSound (fog
, sfx_telept
);
1973 // Randomly select monster to spawn.
1976 // Probability distribution (kind of :),
1977 // decreasing likelihood.
2001 newmobj
= P_SpawnMobj (targ
->x
, targ
->y
, targ
->z
, type
);
2002 if (P_LookForPlayers (newmobj
, true) )
2003 P_SetMobjState (newmobj
, newmobj
->info
->seestate
);
2005 // telefrag anything in this spot
2006 P_TeleportMove (newmobj
, newmobj
->x
, newmobj
->y
);
2008 // remove self (i.e., cube).
2014 void A_PlayerScream (mobj_t
* mo
)
2016 // Default death sound.
2017 int sound
= sfx_pldeth
;
2019 if ( (gamemode
== commercial
)
2020 && (mo
->health
< -50))
2022 // IF THE PLAYER DIES
2023 // LESS THAN -50% WITHOUT GIBBING
2027 S_StartSound (mo
, sound
);