////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 RWS Inc, All Rights Reserved
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of version 2 of the GNU General Public License as published by
// the Free Software Foundation
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
// Ladder.cpp
// Project: Nostril (aka Postal)
// 
// History:
//		06/02/97 JMI	Started.
//
//		06/02/97	JMI	Was not previously setting the position of the smashes'
//							spheres.  Fixed.
//
//		07/09/97	JMI	Now uses m_pRealm->Make2dResPath() to get the fullpath
//							for 2D image components.
//
//////////////////////////////////////////////////////////////////////////////
//
// This CThing-derived class will represent ladders that the CDudes, and 
// perhaps other characters, can use to climb to heights they cannot step up
// to.
//
//////////////////////////////////////////////////////////////////////////////
#define LADDER_CPP

#include "RSPiX.h"
#include <math.h>

#include "Ladder.h"
#include "game.h"
#include "reality.h"

////////////////////////////////////////////////////////////////////////////////
// Macros/types/etc.
////////////////////////////////////////////////////////////////////////////////

#define GUI_FILE_NAME				"res/editor/Ladder.gui"

// This is for edit mode only.
#define LADDER_IMAGE_FILENAME		"ladder.bmp"

#define GUI_ID_LEN					3
#define GUI_ID_HEIGHT				4
#define GUI_ID_ROT					5

#define GUI_ID_TYPE_BASE			10

#define LADDER_ENDS_RADIUS			10

////////////////////////////////////////////////////////////////////////////////
// Variables/data
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Load object (should call base class version!)
////////////////////////////////////////////////////////////////////////////////
int16_t CLadder::Load(								// Returns 0 if successfull, non-zero otherwise
	RFile* pFile,										// In:  File to load from
	bool bEditMode,									// In:  True for edit mode, false otherwise
	int16_t sFileCount,									// In:  File count (unique per file, never 0)
	uint32_t	ulFileVersion)								// In:  Version of file format to load.
	{
	int16_t sResult = CThing::Load(pFile, bEditMode, sFileCount, ulFileVersion);
	if (sResult == 0)
		{
		switch (ulFileVersion)
			{
			default:
			case 15:
			case 14:
			case 13:
			case 12:
			case 11:
			case 10:
			case 9:
			case 8:
			case 7:
			case 6:
			case 5:
			case 4:
			case 3:
			case 2:
			case 1:
				pFile->Read(&m_dX);
				pFile->Read(&m_dY);
				pFile->Read(&m_dZ);
				pFile->Read(&m_sLen);
				pFile->Read(&m_sHeight);
				pFile->Read(&m_sRotY);
				break;
			}

		// Make sure there were no file errors or format errors . . .
		if (!pFile->Error() && sResult == 0)
			{
			// Get resources and initialize.
			sResult = Init();
			}
		else
			{
			sResult = -1;
			TRACE("CLadder::Load(): Error reading from file!\n");
			}
		}

	return sResult;
	}

////////////////////////////////////////////////////////////////////////////////
// Startup object
////////////////////////////////////////////////////////////////////////////////
int16_t CLadder::Startup(void)								// Returns 0 if successfull, non-zero otherwise
	{
	return 0;
	}


////////////////////////////////////////////////////////////////////////////////
// Shutdown object
////////////////////////////////////////////////////////////////////////////////
int16_t CLadder::Shutdown(void)							// Returns 0 if successfull, non-zero otherwise
	{
	return 0;
	}


////////////////////////////////////////////////////////////////////////////////
// Suspend object
////////////////////////////////////////////////////////////////////////////////
void CLadder::Suspend(void)
	{
	m_sSuspend++;
	}


////////////////////////////////////////////////////////////////////////////////
// Resume object
////////////////////////////////////////////////////////////////////////////////
void CLadder::Resume(void)
	{
	m_sSuspend--;
	}

////////////////////////////////////////////////////////////////////////////////
// Update object
////////////////////////////////////////////////////////////////////////////////
void CLadder::Update(void)
	{
	// Do schtuff.
	}

////////////////////////////////////////////////////////////////////////////////
// Render object
////////////////////////////////////////////////////////////////////////////////
void CLadder::Render(void)
	{
	// Doesn't normally draw anything (see EditRender() for render during
	// edit mode).
	}

////////////////////////////////////////////////////////////////////////////////
// Initialize object.
////////////////////////////////////////////////////////////////////////////////
int16_t CLadder::Init(void)	// Returns 0 on success.
	{
	int16_t	sRes	= GetResources();

	float cosp;
	float sinp;
	rspSinCos(float(m_sRotY)), &sinp, &cosp);

	// Set up collision object.
	m_smashTop.m_bits								= CSmash::Ladder;
	m_smashTop.m_sphere.sphere.lRadius		= LADDER_ENDS_RADIUS;
	m_smashTop.m_sphere.sphere.X				= m_dX + cosp * m_sLen;
	m_smashTop.m_sphere.sphere.Y				= m_dY + m_sHeight;
	m_smashTop.m_sphere.sphere.Z				= m_dZ - sinp * m_sLen;
	m_smashBottom.m_bits							= CSmash::Ladder;
	m_smashBottom.m_sphere.sphere.lRadius	= LADDER_ENDS_RADIUS;
	m_smashBottom.m_sphere.sphere.X			= m_dX;
	m_smashBottom.m_sphere.sphere.Y			= m_dY;
	m_smashBottom.m_sphere.sphere.Z			= m_dZ;
	// Update the smash.
	m_pRealm->m_smashatorium.Update(&m_smashTop);
	m_pRealm->m_smashatorium.Update(&m_smashBottom);

	return sRes;
	}

////////////////////////////////////////////////////////////////////////////////
// Get all required resources
////////////////////////////////////////////////////////////////////////////////
int16_t CLadder::GetResources(void)						// Returns 0 if successfull, non-zero otherwise
	{
	int16_t sResult = 0;

	// Safe to call even if no resource.
	FreeResources();

	sResult	= rspGetResource(
		&g_resmgrGame, 
		m_pRealm->Make2dResPath(LADDER_IMAGE_FILENAME),
		&m_sprite.m_pImage);

	return sResult;
	}


////////////////////////////////////////////////////////////////////////////////
// Free all resources
////////////////////////////////////////////////////////////////////////////////
int16_t CLadder::FreeResources(void)						// Returns 0 if successfull, non-zero otherwise
	{
	int16_t sResult = 0;

	if (m_sprite.m_pImage != NULL)
		{
		rspReleaseResource(&g_resmgrGame, &m_sprite.m_pImage);
		}

	return sResult;
	}


////////////////////////////////////////////////////////////////////////////////
// Call to to try to get on the ladder.
// This function will return false if there is already someone on the
// ladder.
////////////////////////////////////////////////////////////////////////////////
bool CLadder::GetOn(		// Returns true, if able to get on, 
								// false otherwise.
	CCharacter* pchar)	// In:  Character attempting to get onto ladder.
	{
	bool	bGotOn	= true;	// Assume success.

	if (m_pcharLadderBoy == NULL)
		{
		m_pcharLadderBoy	= pchar;
		}
	else
		{
		bGotOn	= false;
		}

	return bGotOn;
	}

////////////////////////////////////////////////////////////////////////////////
// Call when you get off the ladder.
// Only call this function, if you have made a successful call to GetOn()
// and have not, since, made a call to this function.
////////////////////////////////////////////////////////////////////////////////
void CLadder::GetOff(void)	// Returns nothing.
	{
	m_pcharLadderBoy	= NULL;
	}

////////////////////////////////////////////////////////////////////////////////
// Get the next position on the ladder.
////////////////////////////////////////////////////////////////////////////////
void CLadder::GetNextPos(	// Returns nothing.
	double*	pdX,				// In:  Current x position.
									// Out: New x position.
	double*	pdY,				// In:  Current y position.
									// Out: New y position.
	double*	pdZ,				// In:  Current z position.
									// Out: New z position.
	double	dDistance)		// In:  Distance to travel. Positive is up.
	{
	TRACE("GetNextPos(): NYI!!\n");
	}

////////////////////////////////////////////////////////////////////////////////
// EOF
////////////////////////////////////////////////////////////////////////////////
