SBSPSS/source/friend/fgary.cpp

480 lines
9.1 KiB
C++
Raw Normal View History

2001-04-27 16:39:10 +02:00
/*=========================================================================
fgary.cpp
Author: CRB
2001-05-25 21:08:35 +02:00
Created:
2001-04-27 16:39:10 +02:00
Project: Spongebob
2001-05-25 21:08:35 +02:00
Purpose:
2001-04-27 16:39:10 +02:00
Copyright (c) 2000 Climax Development Ltd
===========================================================================*/
2001-04-27 17:09:10 +02:00
#ifndef __FRIEND_FGARY_H__
#include "friend\fgary.h"
2001-04-27 16:39:10 +02:00
#endif
#ifndef __GAME_GAME_H__
#include "game\game.h"
#endif
2001-05-30 22:24:02 +02:00
#ifndef __UTILS_HEADER__
#include "utils\utils.h"
#endif
2001-06-06 18:19:00 +02:00
#ifndef __PLAYER_PLAYER_H__
#include "player\player.h"
#endif
#ifndef __VID_HEADER_
#include "system\vid.h"
#endif
2001-06-07 23:44:33 +02:00
#ifndef __ANIM_GARY_HEADER__
#include <ACTOR_GARY_Anim.h>
#endif
2001-07-30 17:27:32 +02:00
#define GARY_SPEED 1
2001-05-30 22:24:02 +02:00
2001-07-28 18:07:56 +02:00
u8 CNpcGaryFriend::m_garySpeech;
2001-08-02 14:45:12 +02:00
u8 CNpcGaryFriend::m_hasReachedDoor;
2001-07-28 18:07:56 +02:00
2001-05-30 22:24:02 +02:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CNpcGaryFriend::postInit()
{
CNpcFriend::postInit();
m_started = false;
2001-07-28 18:07:56 +02:00
m_startMoving = false;
2001-06-06 18:19:00 +02:00
m_fallDeath = false;
m_drawRotation = 0;
2001-07-09 21:38:58 +02:00
m_obstructed = false;
2001-07-28 18:07:56 +02:00
m_garySB = false;
2001-07-25 17:25:54 +02:00
m_garyMeow = false;
2001-06-29 16:57:20 +02:00
m_soundId = (int) NOT_PLAYING;
2001-07-20 21:19:09 +02:00
setCollisionSize( 40, 27 );
setCollisionCentreOffset( 0, -14 );
2001-07-28 18:07:56 +02:00
m_garySpeech = false;
2001-08-03 16:42:00 +02:00
m_isStopping = false;
2001-06-29 16:57:20 +02:00
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CNpcGaryFriend::shutdown()
{
if ( m_soundId != NOT_PLAYING )
{
CSoundMediator::stopAndUnlockSfx( (xmPlayingId) m_soundId );
}
CNpcFriend::shutdown();
2001-05-30 22:24:02 +02:00
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001-04-27 16:39:10 +02:00
2001-04-27 17:09:10 +02:00
void CNpcGaryFriend::think( int _frames )
2001-04-27 16:39:10 +02:00
{
2001-06-29 16:57:20 +02:00
if ( m_soundId != NOT_PLAYING )
{
if( !CSoundMediator::isSfxStillPlaying( (xmPlayingId) m_soundId ) )
{
// unlock sound if it has finished
CSoundMediator::stopAndUnlockSfx( (xmPlayingId) m_soundId );
m_soundId = NOT_PLAYING;
}
}
2001-07-28 18:07:56 +02:00
if ( m_garySB && !m_startMoving )
2001-07-25 17:25:54 +02:00
{
2001-07-28 18:07:56 +02:00
if ( !CSoundMediator::isSpeechPlaying() )
2001-07-25 17:25:54 +02:00
{
2001-07-28 18:07:56 +02:00
if ( m_garyMeow )
{
m_startMoving = true;
}
else
2001-07-25 17:25:54 +02:00
{
2001-07-25 23:02:05 +02:00
m_garyMeow = true;
2001-07-25 17:25:54 +02:00
CSoundMediator::playSpeech( SPEECH_029 );
}
}
}
2001-06-07 23:44:33 +02:00
if ( m_animPlaying )
{
s32 frameCount;
frameCount = m_actorGfx->getFrameCount( m_animNo );
s32 frameShift = ( _frames << 8 ) >> 1;
if ( ( frameCount << 8 ) - m_frame > frameShift )
{
m_frame += frameShift;
}
else
{
m_frame = ( frameCount - 1 ) << 8;
m_animPlaying = false;
}
}
else
{
2001-07-28 18:07:56 +02:00
if ( m_startMoving )
2001-06-07 23:44:33 +02:00
{
m_animNo = ANIM_GARY_SLITHER;
}
else
{
m_animNo = m_data[m_type].idleAnim;
}
m_animPlaying = true;
m_frame = 0;
}
2001-04-27 17:09:10 +02:00
2001-06-06 18:19:00 +02:00
if ( m_fallDeath )
{
m_drawRotation += 64 * _frames;
m_drawRotation &= 4095;
2001-04-27 16:39:10 +02:00
2001-06-06 18:19:00 +02:00
Pos.vy += m_speed * _frames;
2001-04-27 16:39:10 +02:00
2001-06-06 18:19:00 +02:00
if ( m_speed < 5 )
{
m_speed++;
}
2001-04-27 16:39:10 +02:00
2001-07-23 21:26:37 +02:00
DVECTOR const &offset = CLevel::getCameraPos();
2001-05-25 21:08:35 +02:00
2001-06-06 18:19:00 +02:00
if ( Pos.vy - offset.vy > VidGetScrH() )
2001-05-25 21:08:35 +02:00
{
2001-06-06 18:19:00 +02:00
setToShutdown();
2001-05-25 21:08:35 +02:00
}
}
2001-06-06 18:19:00 +02:00
else
2001-04-27 16:39:10 +02:00
{
2001-06-06 18:19:00 +02:00
s8 multiplier = -1 + ( 2 * m_extension );
s32 maxHeight = 20;
s32 fallSpeed = 3;
s8 yMovement = fallSpeed * _frames;
s8 groundHeight;
2001-07-03 00:57:31 +02:00
u8 conveyorOverride = false;
2001-04-27 16:39:10 +02:00
2001-06-06 18:19:00 +02:00
// check vertical collision
2001-04-27 16:39:10 +02:00
2001-07-06 00:27:34 +02:00
groundHeight = CGameScene::getCollision()->getHeightFromGroundNonSB( Pos.vx, Pos.vy, yMovement + 16 );
2001-06-06 18:19:00 +02:00
switch ( CGameScene::getCollision()->getCollisionBlock( Pos.vx, Pos.vy ) & COLLISION_TYPE_MASK )
2001-04-27 16:39:10 +02:00
{
2001-06-06 18:19:00 +02:00
case COLLISION_TYPE_FLAG_DEATH_FALL:
case COLLISION_TYPE_FLAG_DEATH_INSTANT:
case COLLISION_TYPE_FLAG_DEATH_LIQUID:
2001-06-06 23:03:41 +02:00
case COLLISION_TYPE_FLAG_DAMAGE:
2001-06-06 18:19:00 +02:00
{
CPlayer *player = GameScene.getPlayer();
player->takeDamage( DAMAGE__KILL_OUTRIGHT );
m_speed = -5;
m_fallDeath = true;
break;
}
2001-04-27 16:39:10 +02:00
2001-07-03 00:57:31 +02:00
case COLLISION_TYPE_FLAG_MOVE_LEFT:
{
conveyorOverride = true;
2001-07-11 21:03:57 +02:00
int Time = GameState::getFramesSinceLast();
Pos.vx -= Time;
2001-07-13 18:35:46 +02:00
Pos.vx -= _frames;
2001-07-03 00:57:31 +02:00
break;
}
case COLLISION_TYPE_FLAG_MOVE_RIGHT:
{
conveyorOverride = true;
2001-07-11 21:03:57 +02:00
int Time = GameState::getFramesSinceLast();
Pos.vx += Time;
2001-07-13 18:35:46 +02:00
Pos.vx += _frames;
2001-07-03 00:57:31 +02:00
break;
}
2001-06-06 18:19:00 +02:00
default:
break;
2001-04-27 16:39:10 +02:00
}
2001-06-06 18:19:00 +02:00
if ( m_platform )
{
s32 platformHeight = m_platform->getHeightFromPlatformAtPosition( Pos.vx, Pos.vy );
2001-04-27 16:39:10 +02:00
2001-06-06 18:19:00 +02:00
if ( platformHeight < groundHeight )
2001-05-30 22:24:02 +02:00
{
2001-07-30 17:27:32 +02:00
//groundHeight = platformHeight;
groundHeight = 0;
2001-06-06 18:19:00 +02:00
2001-07-30 17:27:32 +02:00
Pos.vy += platformHeight;
}
2001-06-06 18:19:00 +02:00
//return;
2001-04-27 16:39:10 +02:00
}
2001-08-03 16:42:00 +02:00
int garyXMovement = multiplier * GARY_SPEED * _frames;
if ( m_isStopping )
{
int garyRequiredXMovement = m_xStopPos - Pos.vx;
if ( garyRequiredXMovement > 0 )
{
if ( garyXMovement > garyRequiredXMovement )
{
garyXMovement = garyRequiredXMovement;
}
}
else if ( garyRequiredXMovement < 0 )
{
if ( garyXMovement < garyRequiredXMovement )
{
garyXMovement = garyRequiredXMovement;
}
}
else
{
m_isStopping = false;
m_startMoving = false;
m_started = false;
m_animNo = m_data[m_type].idleAnim;
m_animPlaying = true;
m_frame = 0;
m_garyMeow = false;
m_garySB = false;
}
}
2001-06-06 18:19:00 +02:00
if ( groundHeight <= 0 )
2001-04-27 16:39:10 +02:00
{
2001-06-06 18:19:00 +02:00
// groundHeight <= 0 indicates either on ground or below ground
2001-04-27 16:39:10 +02:00
2001-06-06 18:19:00 +02:00
// check horizontal collision
2001-04-27 16:39:10 +02:00
2001-08-03 16:42:00 +02:00
if ( CGameScene::getCollision()->getHeightFromGroundNonSB( Pos.vx + garyXMovement, Pos.vy ) < -maxHeight )
2001-04-27 16:39:10 +02:00
{
// reverse direction
m_extension = !m_extension;
2001-06-06 18:19:00 +02:00
m_reversed = !m_reversed;
2001-04-27 16:39:10 +02:00
}
else
{
2001-06-06 18:19:00 +02:00
// make sure we are on the ground, not below it
Pos.vy += groundHeight;
2001-07-28 18:07:56 +02:00
if ( m_startMoving )
2001-05-30 22:24:02 +02:00
{
2001-07-26 17:45:30 +02:00
if ( canRender() && m_soundId == NOT_PLAYING )
2001-06-29 16:57:20 +02:00
{
m_soundId = (int) CSoundMediator::playSfx( CSoundMediator::SFX_GARY_DE_SNAIL, true );
}
2001-06-01 18:30:37 +02:00
2001-07-09 21:38:58 +02:00
if ( !conveyorOverride && !m_obstructed )
2001-07-03 00:57:31 +02:00
{
2001-08-03 16:42:00 +02:00
Pos.vx += garyXMovement;
2001-07-03 00:57:31 +02:00
}
2001-05-30 22:24:02 +02:00
}
2001-04-27 16:39:10 +02:00
}
}
else
{
2001-06-06 18:19:00 +02:00
// above ground
if ( groundHeight < yMovement )
{
// colliding with ground
Pos.vy += groundHeight;
2001-08-03 16:42:00 +02:00
if ( CGameScene::getCollision()->getHeightFromGroundNonSB( Pos.vx + garyXMovement, Pos.vy ) < -maxHeight )
2001-06-06 18:19:00 +02:00
{
// reverse direction
m_extension = !m_extension;
}
else
{
2001-07-28 18:07:56 +02:00
if ( m_startMoving )
2001-06-06 18:19:00 +02:00
{
2001-07-03 00:57:31 +02:00
if ( m_soundId == NOT_PLAYING )
{
m_soundId = (int) CSoundMediator::playSfx( CSoundMediator::SFX_GARY_DE_SNAIL, true );
}
2001-07-09 21:38:58 +02:00
if ( !conveyorOverride && !m_obstructed )
2001-07-03 00:57:31 +02:00
{
2001-08-03 16:42:00 +02:00
Pos.vx += garyXMovement;
2001-07-03 00:57:31 +02:00
}
2001-06-06 18:19:00 +02:00
}
}
}
else
{
Pos.vy += yMovement;
}
2001-04-27 16:39:10 +02:00
}
}
2001-07-09 21:38:58 +02:00
2001-08-02 16:51:29 +02:00
m_obstructed = false;
2001-07-20 17:03:51 +02:00
// sort out draw rotation
DVECTOR testPos1, testPos2;
testPos1 = testPos2 = Pos;
testPos1.vx -= 10;
testPos2.vx += 10;
2001-08-02 16:51:29 +02:00
int groundDist = CGameScene::getCollision()->getHeightFromGround( testPos1.vx, testPos1.vy, 16 );
if ( abs( groundDist ) > 15 )
{
m_drawRotation = 0;
2001-08-13 17:07:07 +02:00
CNpcThing::think(_frames);
2001-08-02 16:51:29 +02:00
return;
}
testPos1.vy += groundDist;
groundDist = CGameScene::getCollision()->getHeightFromGround( testPos2.vx, testPos2.vy, 16 );
if ( abs( groundDist ) > 15 )
{
m_drawRotation = 0;
2001-08-13 17:07:07 +02:00
CNpcThing::think(_frames);
2001-08-02 16:51:29 +02:00
return;
}
testPos2.vy += groundDist;
2001-07-20 17:03:51 +02:00
s32 xDist = testPos2.vx - testPos1.vx;
s32 yDist = testPos2.vy - testPos1.vy;
s16 heading = ratan2( yDist, xDist );
m_drawRotation = heading;
2001-08-10 20:55:44 +02:00
CNpcThing::think(_frames);
2001-05-30 22:24:02 +02:00
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CNpcGaryFriend::setupWaypoints( sThingActor *ThisActor )
{
if ( ThisActor->PointCount > 1 )
{
u16 *PntList=(u16*)MakePtr(ThisActor,sizeof(sThingActor));
u16 newXPos, newYPos;
// skip first waypoint
PntList++;
PntList++;
// get trigger position
newXPos = (u16) *PntList;
PntList++;
newYPos = (u16) *PntList;
PntList++;
m_triggerPos.vx = newXPos;
m_triggerPos.vy = newYPos;
}
}
2001-05-31 23:36:10 +02:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CNpcGaryFriend::render()
{
CNpcThing::render();
2001-06-06 18:19:00 +02:00
POLY_FT4 *frame;
2001-05-31 23:36:10 +02:00
// Render
if (canRender())
{
DVECTOR &renderPos=getRenderPos();
2001-06-06 18:19:00 +02:00
frame = m_actorGfx->Render(renderPos,m_animNo,(m_frame>>8),m_reversed);
m_actorGfx->RotateScale( frame, renderPos, m_drawRotation, 4096, 4096 );
2001-05-31 23:36:10 +02:00
}
}
2001-06-04 14:54:44 +02:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CNpcGaryFriend::startLeft()
{
start();
m_extension = EXTEND_LEFT;
m_reversed = true;
}
2001-06-04 15:20:30 +02:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CNpcGaryFriend::startRight()
{
start();
m_extension = EXTEND_RIGHT;
m_reversed = false;
}
2001-06-04 22:58:12 +02:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001-06-07 23:44:33 +02:00
void CNpcGaryFriend::start()
{
if ( !m_started )
{
m_animNo = ANIM_GARY_SLITHER;
m_animPlaying = true;
m_frame = 0;
2001-07-28 18:07:56 +02:00
m_started = true;
if ( !m_garySpeech )
{
m_garySpeech = true;
m_garyMeow = false;
m_garySB = true;
CSoundMediator::playSpeech( SPEECH_028 );
}
else
{
m_startMoving = true;
m_garySB = false;
}
2001-06-07 23:44:33 +02:00
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001-08-03 16:42:00 +02:00
void CNpcGaryFriend::stop( int xPos )
2001-06-07 23:44:33 +02:00
{
2001-08-03 16:42:00 +02:00
if ( m_started && !m_isStopping )
2001-06-07 23:44:33 +02:00
{
2001-08-03 16:42:00 +02:00
m_isStopping = true;
m_xStopPos = xPos;
2001-06-07 23:44:33 +02:00
}
}