diff --git a/source/enemy/ngeneric.cpp b/source/enemy/ngeneric.cpp index a1dc71600..78c77b1dd 100644 --- a/source/enemy/ngeneric.cpp +++ b/source/enemy/ngeneric.cpp @@ -80,13 +80,17 @@ void CNpcEnemy::processGenericGotoTarget( int _frames, s32 xDist, s32 yDist, s32 moveX = xDist; } } - else + else if ( xDist < 0 ) { if ( moveX < xDist ) { moveX = xDist; } } + else + { + moveX = 0; + } moveY = preShiftY >> 12; if ( !moveY && preShiftY ) @@ -101,13 +105,17 @@ void CNpcEnemy::processGenericGotoTarget( int _frames, s32 xDist, s32 yDist, s32 moveY = yDist; } } - else + else if ( yDist < 0 ) { if ( moveY < yDist ) { moveY = yDist; } } + else + { + moveY = 0; + } Pos.vx += moveX; Pos.vy += moveY; @@ -188,8 +196,9 @@ void CNpcEnemy::processGenericFixedPathMove( int _frames, s32 *moveX, s32 *moveY { bool pathComplete; bool waypointChange; + s32 xDist, yDist; - s16 headingToTarget = m_npcPath.think( Pos, &pathComplete, &waypointChange ); + s16 headingToTarget = m_npcPath.think( Pos, &pathComplete, &waypointChange, &xDist, &yDist ); /*if ( waypointChange ) { @@ -245,12 +254,50 @@ void CNpcEnemy::processGenericFixedPathMove( int _frames, s32 *moveX, s32 *moveY *moveX = preShiftX / abs( preShiftX ); } + if ( xDist > 0 ) + { + if ( *moveX > xDist ) + { + *moveX = xDist; + } + } + else if ( xDist < 0 ) + { + if ( *moveX < xDist ) + { + *moveX = xDist; + } + } + else + { + *moveX = 0; + } + *moveY = preShiftY >> 12; if ( !(*moveY) && preShiftY ) { *moveY = preShiftY / abs( preShiftY ); } + if ( yDist > 0 ) + { + if ( *moveY > yDist ) + { + *moveY = yDist; + } + } + else if ( yDist < 0 ) + { + if ( *moveY < yDist ) + { + *moveY = yDist; + } + } + else + { + *moveY = 0; + } + *moveVel = ( _frames * m_data[m_type].speed ) << 8; //processGroundCollisionReverse( moveX, moveY ); diff --git a/source/enemy/npc.cpp b/source/enemy/npc.cpp index 5a08799d1..2a03b870f 100644 --- a/source/enemy/npc.cpp +++ b/source/enemy/npc.cpp @@ -617,6 +617,7 @@ void CNpcEnemy::init() m_isShuttingDown = false; m_drawRotation = 0; + m_isCaught = false; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -707,94 +708,103 @@ int CNpcEnemy::getFrameCount() void CNpcEnemy::think(int _frames) { + int moveFrames = _frames; + + if ( moveFrames > 2 ) + { + // make sure enemies don't go berserk if too many frames are dropped + + moveFrames = 2; + } + CEnemyThing::think(_frames); - if ( m_isActive ) + processGenericGetUserDist( _frames, &playerXDist, &playerYDist ); + playerXDistSqr = playerXDist * playerXDist; + playerYDistSqr = playerYDist * playerYDist; + + if ( m_isCaught ) { - processGenericGetUserDist( _frames, &playerXDist, &playerYDist ); - playerXDistSqr = playerXDist * playerXDist; - playerYDistSqr = playerYDist * playerYDist; - - if ( m_animPlaying ) + processCoralBlower( moveFrames ); + } + else + { + if ( m_isActive ) { - s32 frameCount; - - frameCount = getFrameCount(); - - s32 frameShift = ( _frames << 8 ) >> 1; - - if ( ( frameCount << 8 ) - m_frame > frameShift ) + if ( m_animPlaying ) { - m_frame += frameShift; - } - else - { - m_frame = ( frameCount - 1 ) << 8; - m_animPlaying = false; - } - } + s32 frameCount; - switch ( this->m_controlFunc ) - { - case NPC_CONTROL_NONE: - return; + frameCount = getFrameCount(); - case NPC_CONTROL_MOVEMENT: - if ( !processSensor() ) + s32 frameShift = ( _frames << 8 ) >> 1; + + if ( ( frameCount << 8 ) - m_frame > frameShift ) { - int moveFrames = _frames; - - if ( moveFrames > 2 ) - { - // make sure enemies don't go berserk if too many frames are dropped - - moveFrames = 2; - } - - processMovement( moveFrames ); + m_frame += frameShift; } else { - processClose(_frames); + m_frame = ( frameCount - 1 ) << 8; + m_animPlaying = false; } + } - break; + switch ( this->m_controlFunc ) + { + case NPC_CONTROL_NONE: + return; - case NPC_CONTROL_SHOT: - processShot(); + case NPC_CONTROL_MOVEMENT: + if ( !processSensor() ) + { + processMovement( moveFrames ); + } + else + { + processClose(_frames); + } - break; + break; - case NPC_CONTROL_CLOSE: - processClose(_frames); + case NPC_CONTROL_SHOT: + processShot(); - break; + break; - case NPC_CONTROL_COLLISION: - processCollision(); + case NPC_CONTROL_CLOSE: + processClose(_frames); - break; - } + break; - if ( m_heading > 1024 && m_heading < 3072 ) - { - m_reversed = true; - } - else - { - m_reversed = false; + case NPC_CONTROL_COLLISION: + processCollision(); + + break; + } + + if ( m_heading > 1024 && m_heading < 3072 ) + { + m_reversed = true; + } + else + { + m_reversed = false; + } } } - processTimer(_frames); - + if ( !m_isCaught ) + { + processTimer(_frames); + } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void CNpcEnemy::collidedWith( CThing *_thisThing ) { - if ( m_isActive ) + if ( m_isActive && !m_isCaught ) { switch(_thisThing->getThingType()) { @@ -1427,3 +1437,118 @@ void CNpcEnemy::processEnemyCollision( CThing *thisThing ) m_npcPath.incPath(); } } + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CNpcEnemy::processCoralBlowerMovement( int _frames, s32 xDist, s32 yDist ) +{ + s32 moveX, moveY; + s16 headingToTarget; + + headingToTarget = ratan2( yDist, xDist ); + + s32 preShiftX = _frames * 3 * rcos( headingToTarget ); + s32 preShiftY = _frames * 3 * rsin( headingToTarget ); + + moveX = preShiftX >> 12; + if ( !moveX && preShiftX ) + { + moveX = preShiftX / abs( preShiftX ); + } + + if ( xDist > 0 ) + { + if ( moveX > xDist ) + { + moveX = xDist; + } + } + else if ( xDist < 0 ) + { + if ( moveX < xDist ) + { + moveX = xDist; + } + } + else + { + moveX = 0; + } + + moveY = preShiftY >> 12; + if ( !moveY && preShiftY ) + { + moveY = preShiftY / abs( preShiftY ); + } + + if ( yDist > 0 ) + { + if ( moveY > yDist ) + { + moveY = yDist; + } + } + else if ( yDist < 0 ) + { + if ( moveY < yDist ) + { + moveY = yDist; + } + } + else + { + moveY = 0; + } + + Pos.vx += moveX; + Pos.vy += moveY; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CNpcEnemy::processCoralBlower( int _frames ) +{ + s32 targetXDist, targetYDist; + + switch( m_state ) + { + case NPC_CORAL_BLOWER_SUCK: + { + // go to user + + targetXDist = playerXDist; + targetYDist = playerYDist; + + processCoralBlowerMovement( _frames, targetXDist, targetYDist ); + + break; + } + + case NPC_CORAL_BLOWER_RETURN: + { + // go to original position + + targetXDist = m_caughtPos.vx - Pos.vx; + targetYDist = m_caughtPos.vy - Pos.vy; + + processCoralBlowerMovement( _frames, targetXDist, targetYDist ); + + if ( !targetXDist && !targetYDist ) + { + m_state = m_oldState; + m_isCaught = false; + } + + break; + } + + default: + { + m_oldState = m_state; + m_state = NPC_CORAL_BLOWER_SUCK; + m_caughtPos = Pos; + + break; + } + } +} diff --git a/source/enemy/npc.h b/source/enemy/npc.h index adec27680..fea3364eb 100644 --- a/source/enemy/npc.h +++ b/source/enemy/npc.h @@ -176,6 +176,12 @@ protected: NPC_GENERIC_HIT_DEATH_END, }; + enum NPC_CORAL_BLOWER_STATE + { + NPC_CORAL_BLOWER_SUCK = 200, + NPC_CORAL_BLOWER_RETURN = 201, + }; + enum { EXTEND_UP = true, @@ -242,6 +248,9 @@ protected: void reinit(); + void processCoralBlower( int _frames ); + void processCoralBlowerMovement( int _frames, s32 xDist, s32 yDist ); + // data static NPC_DATA m_data[NPC_UNIT_TYPE_MAX]; @@ -274,11 +283,14 @@ protected: DVECTOR m_base; DVECTOR m_initPos; u8 m_state; + u8 m_oldState; u8 m_salvoCount; bool m_animPlaying; bool m_reversed; s32 m_health; bool m_isActive; + u8 m_isCaught; + DVECTOR m_caughtPos; s32 m_frame; int m_animNo; diff --git a/source/enemy/npcpath.cpp b/source/enemy/npcpath.cpp index 19faae214..88495b131 100644 --- a/source/enemy/npcpath.cpp +++ b/source/enemy/npcpath.cpp @@ -239,7 +239,7 @@ bool CNpcPath::getDistToNextWaypoint( DVECTOR currentPos, s32 *distX, s32 *distY return( currentWaypoint->isPointNear( currentPos, distX, distY ) ); } -s32 CNpcPath::think( DVECTOR currentPos, bool *pathComplete, bool *waypointChange ) +s32 CNpcPath::think( DVECTOR currentPos, bool *pathComplete, bool *waypointChange, s32 *distX, s32 *distY ) { if ( !this->waypoint ) { @@ -253,21 +253,19 @@ s32 CNpcPath::think( DVECTOR currentPos, bool *pathComplete, bool *waypointChang currentWaypoint = this->waypoint; } - s32 xDist, yDist; - *pathComplete = false; *waypointChange = false; - if ( currentWaypoint->isPointNear( currentPos, &xDist, &yDist ) ) + if ( currentWaypoint->isPointNear( currentPos, distX, distY ) ) { *pathComplete = incPath(); *waypointChange = true; - xDist = currentWaypoint->pos.vx - currentPos.vx; - yDist = currentWaypoint->pos.vy - currentPos.vy; + *distX = currentWaypoint->pos.vx - currentPos.vx; + *distY = currentWaypoint->pos.vy - currentPos.vy; } - s32 headingToTarget = ratan2( yDist, xDist ); + s32 headingToTarget = ratan2( *distY, *distX ); return( headingToTarget ); } diff --git a/source/enemy/npcpath.h b/source/enemy/npcpath.h index 168791dc3..8e1d9b00c 100644 --- a/source/enemy/npcpath.h +++ b/source/enemy/npcpath.h @@ -44,7 +44,7 @@ public: bool incPath(); void resetPath(); void reversePathDir(); - s32 think( DVECTOR currentPos, bool *pathComplete, bool *waypointChange ); + s32 think( DVECTOR currentPos, bool *pathComplete, bool *waypointChange, s32 *distX, s32 *distY ); bool thinkFlat( DVECTOR currentPos, bool *pathComplete, s32 *distX, s32 *distY, s32 *heading ); bool thinkVertical( DVECTOR currentPos, bool *pathComplete, s32 *distX, s32 *distY, s32 *heading ); bool getDistToNextWaypoint( DVECTOR currentPos, s32 *distX, s32 *distY ); diff --git a/source/enemy/nsjfish.cpp b/source/enemy/nsjfish.cpp index 3a683762c..9fd441523 100644 --- a/source/enemy/nsjfish.cpp +++ b/source/enemy/nsjfish.cpp @@ -118,8 +118,9 @@ void CNpcSmallJellyfishEnemy::processClose( int _frames ) { bool pathComplete; bool waypointChange; + s32 xDist, yDist; - s16 headingToTarget = m_npcPath.think( Pos, &pathComplete, &waypointChange ); + s16 headingToTarget = m_npcPath.think( Pos, &pathComplete, &waypointChange, &xDist, &yDist ); if ( pathComplete ) { diff --git a/source/hazard/hsaw.cpp b/source/hazard/hsaw.cpp index 38d1f0019..b78574c87 100644 --- a/source/hazard/hsaw.cpp +++ b/source/hazard/hsaw.cpp @@ -41,8 +41,9 @@ void CNpcSawbladeHazard::processMovement( int _frames ) { bool pathComplete; bool waypointChange; + s32 xDist, yDist; - s16 headingToTarget = m_npcPath.think( Pos, &pathComplete, &waypointChange ); + s16 headingToTarget = m_npcPath.think( Pos, &pathComplete, &waypointChange, &xDist, &yDist ); if ( !pathComplete ) { diff --git a/source/platform/plinear.cpp b/source/platform/plinear.cpp index 424b917fd..b8ac206b7 100644 --- a/source/platform/plinear.cpp +++ b/source/platform/plinear.cpp @@ -28,11 +28,12 @@ void CNpcLinearPlatform::processMovement( int _frames ) { s32 moveX = 0, moveY = 0; s32 moveDist = 0; + s32 xDist, yDist; bool pathComplete; bool waypointChange; - s16 headingToTarget = m_npcPath.think( Pos, &pathComplete, &waypointChange ); + s16 headingToTarget = m_npcPath.think( Pos, &pathComplete, &waypointChange, &xDist, &yDist ); if ( !pathComplete ) { @@ -83,12 +84,50 @@ void CNpcLinearPlatform::processMovement( int _frames ) moveX = preShiftX / abs( preShiftX ); } + if ( xDist > 0 ) + { + if ( moveX > xDist ) + { + moveX = xDist; + } + } + else if ( xDist < 0 ) + { + if ( moveX < xDist ) + { + moveX = xDist; + } + } + else + { + moveX = 0; + } + moveY = preShiftY >> 12; if ( !moveY && preShiftY ) { moveY = preShiftY / abs( preShiftY ); } + if ( yDist > 0 ) + { + if ( moveY > yDist ) + { + moveY = yDist; + } + } + else if ( yDist < 0 ) + { + if ( moveY < yDist ) + { + moveY = yDist; + } + } + else + { + moveY = 0; + } + //processGroundCollisionReverse( moveX, moveY ); }