/*=========================================================================

	pconveyr.cpp

	Author:		CRB
	Created: 
	Project:	Spongebob
	Purpose: 

	Copyright (c) 2001 Climax Development Ltd

===========================================================================*/

#ifndef __PLATFORM_PCONVEYR_H__
#include "platform\pconveyr.h"
#endif

#ifndef	__UTILS_HEADER__
#include	"utils\utils.h"
#endif

#ifndef __GAME_GAME_H__
#include "game\game.h"
#endif

#ifndef __PLATFORM_PFALLNOR_H__
#include "platform\pfallnor.h"
#endif

#ifndef __VID_HEADER_
#include "system\vid.h"
#endif


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CNpcConveyorPlatformGenerator::collidedWith(CThing *_thisThing)
{
	// do nothing
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CNpcConveyorPlatformGenerator::render()
{
	// no rendering
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CNpcConveyorPlatformGenerator::think( int _frames )
{
	m_timer -= _frames;

	if ( m_timer < 0 )
	{
		s32 second = GameState::getOneSecondInFrames();

		m_timer = second;

		m_timer += m_dataPtr->initTimer * second;

		m_timer += second - ( getRnd() % ( 2 * second ) );

		//m_timer = ( 3 * GameState::getOneSecondInFrames() ) + ( getRnd() % ( ( m_data[m_type].initTimer - 1 ) * GameState::getOneSecondInFrames() ) );

		// generate new conveyor platform

		CNpcPlatform *newPlatform = NULL;
		newPlatform = CNpcPlatform::Create( NPC_CONVEYOR_PLATFORM );

		ASSERT(newPlatform);

		newPlatform->setThingSubType( NPC_CONVEYOR_PLATFORM );
		newPlatform->setGraphic( m_graphicNum );

		DVECTOR startPos = Pos;
		newPlatform->init( startPos );

		newPlatform->setWaypointCount( m_npcPath.getWaypointCount() );
		newPlatform->setWaypointPtr( m_npcPath.getWaypointPtr() );

		newPlatform->setTiltable( false );
		newPlatform->postInit();
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CNpcConveyorPlatform::postInit()
{
	CNpcPlatform::postInit();

	m_npcPath.setPathType( CNpcPath::SINGLE_USE_PATH );

	m_spinFinish = false;
	m_rotation = 0;

	s32 minX, maxX, minY, maxY;

	m_npcPath.getPathXExtents( &minX, &maxX );
	m_npcPath.getPathYExtents( &minY, &maxY );

	m_thinkArea.x1 = minX;
	m_thinkArea.x2 = maxX;
	m_thinkArea.y1 = minY;
	m_thinkArea.y2 = maxY;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CNpcConveyorPlatform::processMovement( int _frames )
{
	s32 moveX = 0, moveY = 0;
	s32 distX, distY;
	bool pathComplete, waypointChange;

	if ( m_spinFinish )
	{
		m_rotation += 64 * _frames;
		m_rotation &= 4095;

		DVECTOR const &offset = CLevel::getCameraPos();

		Pos.vy += 3 * _frames;

		s32 yPos = Pos.vy - offset.vy;

		if ( yPos < 0 || yPos > VidGetScrH() )
		{
			setToShutdown();
		}
	}
	else
	{
		m_npcPath.think( Pos, &pathComplete, &waypointChange, &distX, &distY );

		if ( pathComplete )
		{
			m_spinFinish = true;
		}
		else
		{
			if ( distX )
			{
				int Time = GameState::getFramesSinceLast();

				moveX = distX;

				if ( moveX > Time )
				{
					moveX = Time;
				}
				else if ( moveX < -Time )
				{
					moveX = -Time;
				}
			}
			else
			{
				moveY = distY;

				s32 verticalMovement = 3 * _frames;

				if ( moveY > verticalMovement )
				{
					moveY = verticalMovement;
				}
				else if ( moveY < -verticalMovement )
				{
					moveY = -verticalMovement;
				}
			}
		}
	}

	Pos.vx += moveX;
	Pos.vy += moveY;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CNpcConveyorPlatform::collidedWith( CThing *_thisThing )
{
	switch(_thisThing->getThingType())
	{
		case TYPE_PLAYER:
		{
			CPlayer *player;
//			DVECTOR	playerPos;
//			CRECT	collisionArea;

			// Only interested in SBs feet colliding with the box (pkg)
			player=(CPlayer*)_thisThing;
DVECTOR const &playerPos=player->getPos();
CRECT const &collisionArea=getCollisionArea();

			s32 threshold = abs( collisionArea.y2 - collisionArea.y1 );

			if ( threshold > 16 )
			{
				threshold = 16;
			}

			if( playerPos.vx >= collisionArea.x1 && playerPos.vx <= collisionArea.x2 )
			{
				if ( checkCollisionDelta( _thisThing, threshold, collisionArea ) )
				{
					player->setPlatform( this );

					m_contact = true;
				}
				else
				{
					if( playerPos.vy >= collisionArea.y1 && playerPos.vy <= collisionArea.y2 )
					{
						int height = getHeightFromPlatformAtPosition( playerPos.vx, playerPos.vy );

						if ( height >= -threshold && height < 1 )
						{
							player->setPlatform( this );

							m_contact = true;
						}
						else
						{
							int distLeft, distRight;

							DVECTOR const &playerCollisionSize = player->getCollisionSize();

							distLeft = collisionArea.x1 - playerPos.vx - ( playerCollisionSize.vx >> 1 );
							distRight = collisionArea.x2 - playerPos.vx + ( playerCollisionSize.vx >> 1 );

							DVECTOR playerShove;
							playerShove.vy = 0;

							if ( abs( distLeft ) < abs( distRight ) )
							{
								playerShove.vx = distLeft;
							}
							else
							{
								playerShove.vx = distRight;
							}

							player->shove( playerShove );
						}
					}
				}
			}

			break;
		}

		case TYPE_NPC:
			break;

		case TYPE_HAZARD:
		{
			if ( !m_spinFinish )
			{
				m_spinFinish = true;
			}

			break;
		}

		default:
			ASSERT(0);
			break;
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CNpcConveyorPlatform::render()
{
	if ( m_isActive )
	{
		CPlatformThing::render();

		// Render
		if (canRender())
		{
			DVECTOR &renderPos=getRenderPos();

			SVECTOR rotation;
			rotation.vx = 0;
			rotation.vy = 0;
			rotation.vz = m_rotation;

			VECTOR scale;
			scale.vx = ONE;
			scale.vy = ONE;
			scale.vz = ONE;

			m_modelGfx->Render(renderPos,&rotation,&scale);
		}
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

int CNpcConveyorPlatform::checkCollisionAgainst(CThing *_thisThing, int _frames)
{
	if ( m_spinFinish )
	{
		return( false );
	}
	else
	{
		return( CNpcPlatform::checkCollisionAgainst( _thisThing, _frames ) );
	}
}