diff --git a/source/enemy/nfdutch.cpp b/source/enemy/nfdutch.cpp index c3bc08b5f..f7a3c093f 100644 --- a/source/enemy/nfdutch.cpp +++ b/source/enemy/nfdutch.cpp @@ -68,6 +68,20 @@ void CNpcFlyingDutchmanEnemy::postInit() } m_fireCount = 0; + + m_invulnerableTimer = 0; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CNpcFlyingDutchmanEnemy::think( int _frames ) +{ + if ( m_invulnerableTimer > 0 ) + { + m_invulnerableTimer -= _frames; + } + + CNpcEnemy::think( _frames ); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -325,6 +339,8 @@ void CNpcFlyingDutchmanEnemy::processShot( int _frames ) case NPC_GENERIC_HIT_RECOIL: { + m_invulnerableTimer = 2 * GameState::getOneSecondInFrames(); + if ( !m_animPlaying ) { m_state = 0; @@ -447,3 +463,89 @@ void CNpcFlyingDutchmanEnemy::render() } } } + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CNpcFlyingDutchmanEnemy::collidedWith(CThing *_thisThing) +{ + if ( m_isActive && !m_isCaught && !m_isDying ) + { + switch(_thisThing->getThingType()) + { + case TYPE_PLAYER: + { + CPlayer *player = (CPlayer *) _thisThing; + + ATTACK_STATE playerState = player->getAttackState(); + + if(playerState==ATTACK_STATE__NONE) + { + if ( !player->isRecoveringFromHit() ) + { + switch( m_data[m_type].detectCollision ) + { + case DETECT_NO_COLLISION: + { + // ignore + + break; + } + + case DETECT_ALL_COLLISION: + { + m_oldControlFunc = m_controlFunc; + m_controlFunc = NPC_CONTROL_COLLISION; + + processUserCollision( _thisThing ); + + break; + } + + case DETECT_ATTACK_COLLISION_GENERIC: + { + processAttackCollision(); + processUserCollision( _thisThing ); + + break; + } + } + } + } + else if ( m_invulnerableTimer <= 0 ) + { + // player is attacking, respond appropriately + + if ( m_controlFunc != NPC_CONTROL_SHOT ) + { + if(playerState==ATTACK_STATE__BUTT_BOUNCE) + { + player->justButtBouncedABadGuy(); + } + m_controlFunc = NPC_CONTROL_SHOT; + m_state = NPC_GENERIC_HIT_CHECK_HEALTH; + + drawAttackEffect(); + } + } + + break; + } + + case TYPE_ENEMY: + { + CNpcEnemy *enemy = (CNpcEnemy *) _thisThing; + + if ( canCollideWithEnemy() && enemy->canCollideWithEnemy() ) + { + processEnemyCollision( _thisThing ); + } + + break; + } + + default: + ASSERT(0); + break; + } + } +} diff --git a/source/enemy/nfdutch.h b/source/enemy/nfdutch.h index 4bbb5c6d8..e0bbdac28 100644 --- a/source/enemy/nfdutch.h +++ b/source/enemy/nfdutch.h @@ -17,6 +17,7 @@ class CNpcFlyingDutchmanEnemy : public CNpcEnemy { public: + virtual void think( int _frames ); virtual void postInit(); void render(); virtual void shutdown(); @@ -24,6 +25,7 @@ protected: virtual void processClose( int _frames ); virtual void processMovement( int _frames ); virtual void processShot( int _frames ); + virtual void collidedWith(CThing *_thisThing); enum NPC_FLYING_DUTCHMAN_STATE { @@ -36,6 +38,7 @@ protected: bool m_meterOn; u8 m_inRange; u8 m_fireCount; + s32 m_invulnerableTimer; }; #endif \ No newline at end of file diff --git a/source/enemy/nmjfish.cpp b/source/enemy/nmjfish.cpp index 148b38294..0de2e0089 100644 --- a/source/enemy/nmjfish.cpp +++ b/source/enemy/nmjfish.cpp @@ -85,6 +85,7 @@ void CNpcMotherJellyfishEnemy::postInit() m_renderScale = 2048 + ( ( ( 4096 - 2048 ) * m_health ) / m_data[m_type].initHealth ); m_speed = m_data[m_type].speed + ( ( 3 * ( m_data[m_type].initHealth - m_health ) ) / m_data[m_type].initHealth ); m_pauseTimer = m_maxPauseTimer = ( GameState::getOneSecondInFrames() * m_health ) / m_data[m_type].initHealth; + m_invulnerableTimer = 0; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -153,6 +154,11 @@ void CNpcMotherJellyfishEnemy::setupWaypoints( sThingActor *ThisActor ) void CNpcMotherJellyfishEnemy::processMovement( int _frames ) { + if ( m_invulnerableTimer > 0 ) + { + m_invulnerableTimer -= _frames; + } + switch( m_state ) { case MOTHER_JELLYFISH_CYCLE: @@ -580,6 +586,8 @@ void CNpcMotherJellyfishEnemy::processShot( int _frames ) m_controlFunc = NPC_CONTROL_MOVEMENT; + m_invulnerableTimer = 2 * GameState::getOneSecondInFrames(); + break; } } @@ -591,6 +599,85 @@ void CNpcMotherJellyfishEnemy::collidedWith(CThing *_thisThing) { if ( m_state == MOTHER_JELLYFISH_CYCLE ) { - CNpcEnemy::collidedWith( _thisThing ); + if ( m_isActive && !m_isCaught && !m_isDying ) + { + switch(_thisThing->getThingType()) + { + case TYPE_PLAYER: + { + CPlayer *player = (CPlayer *) _thisThing; + + ATTACK_STATE playerState = player->getAttackState(); + + if(playerState==ATTACK_STATE__NONE) + { + if ( !player->isRecoveringFromHit() ) + { + switch( m_data[m_type].detectCollision ) + { + case DETECT_NO_COLLISION: + { + // ignore + + break; + } + + case DETECT_ALL_COLLISION: + { + m_oldControlFunc = m_controlFunc; + m_controlFunc = NPC_CONTROL_COLLISION; + + processUserCollision( _thisThing ); + + break; + } + + case DETECT_ATTACK_COLLISION_GENERIC: + { + processAttackCollision(); + processUserCollision( _thisThing ); + + break; + } + } + } + } + else if ( m_invulnerableTimer <= 0 ) + { + // player is attacking, respond appropriately + + if ( m_controlFunc != NPC_CONTROL_SHOT ) + { + if(playerState==ATTACK_STATE__BUTT_BOUNCE) + { + player->justButtBouncedABadGuy(); + } + m_controlFunc = NPC_CONTROL_SHOT; + m_state = NPC_GENERIC_HIT_CHECK_HEALTH; + + drawAttackEffect(); + } + } + + break; + } + + case TYPE_ENEMY: + { + CNpcEnemy *enemy = (CNpcEnemy *) _thisThing; + + if ( canCollideWithEnemy() && enemy->canCollideWithEnemy() ) + { + processEnemyCollision( _thisThing ); + } + + break; + } + + default: + ASSERT(0); + break; + } + } } } diff --git a/source/enemy/nmjfish.h b/source/enemy/nmjfish.h index ce92d21b2..9f9889647 100644 --- a/source/enemy/nmjfish.h +++ b/source/enemy/nmjfish.h @@ -59,6 +59,7 @@ protected: s32 m_halfCycleWidth; bool m_meterOn; s16 m_renderScale; + s32 m_invulnerableTimer; CFXJellyFishLegs *legs[4]; DVECTOR legsPos[4]; diff --git a/source/enemy/npcdata.cpp b/source/enemy/npcdata.cpp index c821f2620..b75a5fe11 100644 --- a/source/enemy/npcdata.cpp +++ b/source/enemy/npcdata.cpp @@ -930,7 +930,7 @@ CNpcEnemy::NPC_DATA CNpcEnemy::m_data[NPC_UNIT_TYPE_MAX] = false, 3, 2048, - DETECT_NO_COLLISION, + DETECT_ALL_COLLISION, DAMAGE__HIT_ENEMY, 50, 0, diff --git a/source/enemy/nsshark.cpp b/source/enemy/nsshark.cpp index e0ef923e5..a43c20522 100644 --- a/source/enemy/nsshark.cpp +++ b/source/enemy/nsshark.cpp @@ -62,6 +62,20 @@ void CNpcSubSharkEnemy::postInit() m_health = CLevel::getBossHealth(); m_speed = m_data[m_type].speed + ( ( 3 * ( m_data[m_type].initHealth - m_health ) ) / m_data[m_type].initHealth ); } + + m_invulnerableTimer = 0; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CNpcSubSharkEnemy::think( int _frames ) +{ + if ( m_invulnerableTimer > 0 ) + { + m_invulnerableTimer -= _frames; + } + + CNpcEnemy::think( _frames ); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -344,6 +358,8 @@ void CNpcSubSharkEnemy::processShot( int _frames ) case NPC_GENERIC_HIT_RECOIL: { + m_invulnerableTimer = 2 * GameState::getOneSecondInFrames(); + if ( !m_animPlaying ) { m_state = 0; @@ -466,3 +482,89 @@ void CNpcSubSharkEnemy::render() } } } + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CNpcSubSharkEnemy::collidedWith(CThing *_thisThing) +{ + if ( m_isActive && !m_isCaught && !m_isDying ) + { + switch(_thisThing->getThingType()) + { + case TYPE_PLAYER: + { + CPlayer *player = (CPlayer *) _thisThing; + + ATTACK_STATE playerState = player->getAttackState(); + + if(playerState==ATTACK_STATE__NONE) + { + if ( !player->isRecoveringFromHit() ) + { + switch( m_data[m_type].detectCollision ) + { + case DETECT_NO_COLLISION: + { + // ignore + + break; + } + + case DETECT_ALL_COLLISION: + { + m_oldControlFunc = m_controlFunc; + m_controlFunc = NPC_CONTROL_COLLISION; + + processUserCollision( _thisThing ); + + break; + } + + case DETECT_ATTACK_COLLISION_GENERIC: + { + processAttackCollision(); + processUserCollision( _thisThing ); + + break; + } + } + } + } + else if ( m_invulnerableTimer <= 0 ) + { + // player is attacking, respond appropriately + + if ( m_controlFunc != NPC_CONTROL_SHOT ) + { + if(playerState==ATTACK_STATE__BUTT_BOUNCE) + { + player->justButtBouncedABadGuy(); + } + m_controlFunc = NPC_CONTROL_SHOT; + m_state = NPC_GENERIC_HIT_CHECK_HEALTH; + + drawAttackEffect(); + } + } + + break; + } + + case TYPE_ENEMY: + { + CNpcEnemy *enemy = (CNpcEnemy *) _thisThing; + + if ( canCollideWithEnemy() && enemy->canCollideWithEnemy() ) + { + processEnemyCollision( _thisThing ); + } + + break; + } + + default: + ASSERT(0); + break; + } + } +} diff --git a/source/enemy/nsshark.h b/source/enemy/nsshark.h index 3e2c7cccf..e6eca3e41 100644 --- a/source/enemy/nsshark.h +++ b/source/enemy/nsshark.h @@ -17,6 +17,7 @@ class CNpcSubSharkEnemy : public CNpcEnemy { public: + virtual void think( int _frames ); virtual void postInit(); void render(); virtual void shutdown(); @@ -24,6 +25,7 @@ protected: virtual void processClose( int _frames ); virtual void processMovement( int _frames ); virtual void processShot( int _frames ); + virtual void collidedWith(CThing *_thisThing); enum NPC_SUB_SHARK_STATE { @@ -40,6 +42,7 @@ protected: u8 m_salvoCount; bool m_meterOn; + s32 m_invulnerableTimer; }; #endif \ No newline at end of file