@ -1259,6 +1259,46 @@ void MonsterAttackPlayer(Monster &monster, Player &player, int hit, int minDam,
}
}
struct MeleeAttackWindow {
int frame ;
int toHitDelta ;
int minDamageDelta ;
int maxDamageDelta ;
bool playAttackSound ;
} ;
struct MeleeAttackWindowsView {
const MeleeAttackWindow * data ;
size_t size ;
} ;
MeleeAttackWindowsView GetExtraMeleeAttackWindows ( const Monster & monster )
{
static constexpr MeleeAttackWindow MagmaAttackWindows [ ] = {
{ 8 , 10 , - 2 , - 2 , true } ,
} ;
static constexpr MeleeAttackWindow StormAttackWindows [ ] = {
{ 12 , - 20 , 4 , 4 , true } ,
} ;
switch ( monster . type ( ) . type ) {
case MT_NMAGMA :
case MT_YMAGMA :
case MT_BMAGMA :
case MT_WMAGMA :
return { MagmaAttackWindows , std : : size ( MagmaAttackWindows ) } ;
case MT_STORM :
case MT_RSTORM :
case MT_STORML :
case MT_MAEL :
return { StormAttackWindows , std : : size ( StormAttackWindows ) } ;
}
return { nullptr , 0 } ;
}
void MonsterAttackEnemy ( Monster & monster , int hit , int minDam , int maxDam )
{
if ( ( monster . flags & MFLAG_NO_ENEMY ) = = 0 ) {
@ -1271,22 +1311,32 @@ void MonsterAttackEnemy(Monster &monster, int hit, int minDam, int maxDam)
bool MonsterAttack ( Monster & monster )
{
if ( monster . animInfo . currentFrame = = monster . data ( ) . animFrameNum - 1 ) {
MonsterAttackEnemy ( monster , monster . toHit ( sgGameInitInfo . nDifficulty ) , monster . minDamage , monster . maxDamage ) ;
const int currentFrame = monster . animInfo . currentFrame ;
const int baseToHit = monster . toHit ( sgGameInitInfo . nDifficulty ) ;
if ( currentFrame = = monster . data ( ) . animFrameNum - 1 ) {
MonsterAttackEnemy ( monster , baseToHit , monster . minDamage , monster . maxDamage ) ;
if ( monster . ai ! = MonsterAIID : : Snake )
PlayEffect ( monster , MonsterSound : : Attack ) ;
}
if ( IsAnyOf ( monster . type ( ) . type , MT_NMAGMA , MT_YMAGMA , MT_BMAGMA , MT_WMAGMA ) & & monster . animInfo . currentFrame = = 8 ) {
MonsterAttackEnemy ( monster , monster . toHit ( sgGameInitInfo . nDifficulty ) + 10 , monster . minDamage - 2 , monster . maxDamage - 2 ) ;
PlayEffect ( monster , MonsterSound : : Attack ) ;
}
if ( IsAnyOf ( monster . type ( ) . type , MT_STORM , MT_RSTORM , MT_STORML , MT_MAEL ) & & monster . animInfo . currentFrame = = 12 ) {
MonsterAttackEnemy ( monster , monster . toHit ( sgGameInitInfo . nDifficulty ) - 20 , monster . minDamage + 4 , monster . maxDamage + 4 ) ;
const MeleeAttackWindowsView extraAttackWindows = GetExtraMeleeAttackWindows ( monster ) ;
for ( size_t i = 0 ; i < extraAttackWindows . size ; + + i ) {
const MeleeAttackWindow & window = extraAttackWindows . data [ i ] ;
if ( currentFrame ! = window . frame )
continue ;
PlayEffect ( monster , MonsterSound : : Attack ) ;
MonsterAttackEnemy (
monster ,
baseToHit + window . toHitDelta ,
monster . minDamage + window . minDamageDelta ,
monster . maxDamage + window . maxDamageDelta ) ;
if ( window . playAttackSound )
PlayEffect ( monster , MonsterSound : : Attack ) ;
}
if ( monster . ai = = MonsterAIID : : Snake & & monster . animInfo . currentFrame = = 0 )
if ( monster . ai = = MonsterAIID : : Snake & & currentFrame = = 0 )
PlayEffect ( monster , MonsterSound : : Attack ) ;
if ( monster . animInfo . isLastFrame ( ) ) {
M_StartStand ( monster , monster . direction ) ;