/*
* This file is part of UAS2.
*
* UAS2 is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* UAS2 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 UASv1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

/**
 *	@file cPortal.cpp
 *	Implements functionality for portals.
 *
 *	This class is referenced whenever a portal is created, used, or assessed.
 *	Inherits from the cObject class.
 */

#include "Client.h"
#include "MasterServer.h"
#include "Object.h"
#include "WorldManager.h"

/***************
 *	constructors
 **************/

/**
 *	Handles the creation of portals.
 *
 *	Called whenever a portal object should be initialized.
 */
cPortal::cPortal( DWORD dwGUID, DWORD dwColor, cLocation *Loc, cLocation *destLoc, char *szName, char *szDescription, DWORD dwLowerRestrict, DWORD dwHigherRestrict )
{
	SetLocation(Loc);
	SetDestination(destLoc);
	m_dwGUID = dwGUID;
	m_strName.assign( szName );
	m_strDescription.assign( szDescription );

	m_dwLowerRestriction = dwLowerRestrict;
	m_dwHigherRestriction = dwHigherRestrict;
	m_fStatic = TRUE;

	m_wPortalMode = 3084; // Will add special case code later, for now all are Auto Use Portals
	// Object Flags appear to be Static
	m_dwObjectsFlag1 = 0x00010080;
	m_dwObjectsFlag2 = 0x00040014; 

	switch(dwColor)
			{
			case 17:
				m_dwModel = 1490; // 0x05D2
				break;
			case 1:
				m_dwModel = 1491;
				break;
			case 4:
				m_dwModel = 1492;
				break;
			case 6:
				m_dwModel = 1493; // 0x05D5
				break;
			case 3:
				m_dwModel = 1494;
				break;
			case 5: 
				m_dwModel = 435;  // 0x01B3
				break;
			case 2:
				m_dwModel = 1780;
				break;
			default:
				m_dwModel = 435;
			}
	m_wModel		=	1032;
	m_wIcon			=	4203;
	m_wAnimConfig	= 0x3;
}

/**********
 *	methods
 *********/

/**
 *	Handles the message sent for the creation of portals in the world.
 *
 *	This function is called whenever a portal should be created in the world for a client.
 *
 *	@return cMessage - Returns a Create Object (0x0000F745) server message.
 */
cMessage cPortal::CreatePacket()
{
	cMessage cmCreate;
	unsigned char bUnknown[] = {
		0x00, 0x00, // Animation type 0 - 1
		0x3D, 0x00, // Starting Stance 2 - 3
		0x00, 0xF0, 0x99, 0x02, // Unknown - Flag 0x00000002 in it 4 - 7
	};

	cmCreate	<< 0xF745L 
				<< m_dwGUID 
				<< BYTE( 0x11 ) 
				<< BYTE( 0 )  // Special Portals Might have 1
				<< BYTE( 0 ) 
				<< BYTE( 0 );
	//If Portal has a Palette Change will be 0xFF(-255)
	// cmCreate << WORD(0xFF);
	DWORD dwFlags = 0x00018003L; // Appears to be fixed for all Portal Types

	cmCreate << dwFlags;
	cmCreate << WORD( m_wPortalMode ); 
	// This changes (so far only 2 variations occur)
	// 0x3076 - House Portals (Click to Use?)
	// 0x3084 - Normal Portals

	cmCreate << WORD( 0x0000 ); // wUnknown1 Always 0x0000

	// MASK 0x00010000 unknown Bytes - Starting Animation  
	cmCreate << 0x08L;
	cmCreate.pasteData(bUnknown,sizeof(bUnknown));
	cmCreate << 0x0L; // wUnknown_1 Always 0x0000

	// MASK 0x00008000 - Location 
	if ( !m_fIsOwned )
		cmCreate.CannedData( (BYTE *)&m_Location, sizeof( cLocation ) );
	
	// MASK 0x00000002 Animation Set
	DWORD dwAnimC = 0x09000000L + m_wAnimConfig; 
	// Always 0x9000003 Will still do it this way incase we find a variant
	cmCreate << dwAnimC;

	// MASK 0x00000001 ModelNumber
	DWORD dwModel = 0x02000000L + m_dwModel; // Set on object create based on Database info
	cmCreate << dwModel;

	// SeaGreens
	WORD wNuminteracts = 0x0;
	WORD wNumbubbles = 0x0;
	WORD wNumJumps = 0x0;
	WORD wNumOverrides = 0x0;
	WORD wUnkFlag8 = 0x0;
	WORD wUnkFlag10 = 0x0;
	
	cmCreate	<< WORD(70) // m_wPositionSequence
				<< wNuminteracts
				<< wNumbubbles 
				<< wNumJumps 
				<< WORD(0x0000) // m_wNumPortals 
				<< WORD(0x0001) // m_wNumAnims 
				<< wNumOverrides 
				<< wUnkFlag8
				<< m_wNumLogins
				<< wUnkFlag10;

	DWORD dwFlags2 = 0x00800030; 
	// This changes (so far only 2 variations occur)
	// 0x02800030 for House Portals
	// 0x00800030 for Normal Portals
	
	cmCreate	<< dwFlags2 
				<< m_strName.c_str( ) 
				<< WORD(m_wModel)  // Varies based on Portal Color
				<< WORD(0x106B);   // Icon is static value all portals
				
	//DWORD dwObjectFlags1 = 0x80L;	
	cmCreate << m_dwObjectsFlag1;

	//DWORD dwObjectFlags2 = 0x1014L;
	cmCreate << m_dwObjectsFlag2 ;

	// Masked against dwFlags2
	// Mask 0x0010 dwUnknown_v2 
	// Always 32
	cmCreate << DWORD(0x20);

	// Mask 0x0020 - unknown_v3 Approach Distance
	cmCreate << float(-0.1);
	
	// Mask 0x00800000 - unknown_v6
	// Always 4
	cmCreate << BYTE(0x04);

	this->item_type = 1000;
	
	return cmCreate;
}	

/**
 *	Handles the actions of portal objects.
 *
 *	This function is called whenever a portal is used or should perform an action.
 */
void cPortal::Action(cClient *who)
{
	if(m_dwHigherRestriction !=0 && who->m_pcAvatar->m_cStats.m_dwLevel > m_dwHigherRestriction )
	{
		cMasterServer::ServerMessage(ColorBlue,NULL,"You are to powerful to use this portal!");
	}
	else if (who->m_pcAvatar->m_cStats.m_dwLevel < m_dwLowerRestriction)
	{
		cMasterServer::ServerMessage(ColorBlue,NULL,"You are to weak to use this portal!");
	}
	else
	{
		cWorldManager::TeleportAvatar( who, m_cDestination );
	}

	cMessage cmActionComplete;
	cmActionComplete << 0xF7B0L << who->m_pcAvatar->GetGUID( ) << ++who->m_dwF7B0Sequence << 0x01C7L << 0L;
	who->AddPacket(WORLD_SERVER,cmActionComplete,4);
}

/**
 *	Handles the assessment of portal objects.
 *
 *	This function is called whenever a portal is assessed by a client.
 *
 *	Returns a Game Event (0x0000F7B0) server message of type Identify Object (0x000000C9).
 */
void cPortal::Assess(cClient *pcAssesser)
{
	cMessage cmAssess;
	DWORD flags = 0x00000009;
	cmAssess << 0xF7B0L << pcAssesser->m_pcAvatar->GetGUID() << ++pcAssesser->m_dwF7B0Sequence << 0xC9L << m_dwGUID;

	//Cubem0j0:  Check for level restrictions on this portal
	if( m_dwLowerRestriction > 0)
	{
		
		cmAssess	<< flags 
					<< 0x01L				//Success = 0x01, Failure = 0x00
					<< WORD(0x0003)			//Total number of DWORDS
					<< WORD(0x0010)			//Unknown
					<< 0x56L				//Min Level
					<< DWORD(this->m_dwLowerRestriction)
					<< 0x57L				//Max Level
					<< DWORD(this->m_dwHigherRestriction)
					<< 0x6FL				//Portal Restriction flags
					<< 0x01L				// ?

					<< WORD(0x0002)			//Count (as above) total number of DWORDS
					<< WORD(0x0008)			//Unknown
					<< 0x10L				//Long Description (for portals we use the name)
					<< this->m_strName.c_str()
					<< 0x26L				//Destination:
					<< this->m_strDescription.c_str();

	}
	else
	{
		cmAssess	<< flags 
					<< 0x01L				//Success = 0x01, Failure = 0x00
					<< WORD(0x0001)			//Total number of DWORDS
					<< WORD(0x0010)			//Unknown


					<< 0x6FL				//Portal Restriction flags
					<< 0x01L				// ?

					<< WORD(0x0002)			//Count (as above) total number of DWORDS
					<< WORD(0x0008)			//Unknown
					<< 0x10L				//Long Description (for portals we use the name)
					<< this->m_strName.c_str()
					<< 0x26L				//Destination:
					<< this->m_strDescription.c_str();
	}

	pcAssesser->AddPacket(WORLD_SERVER, cmAssess,4);
	
	cMessage cmActionComplete;
	cmActionComplete << 0xF7B0L << pcAssesser->m_pcAvatar->GetGUID( ) << ++pcAssesser->m_dwF7B0Sequence << 0x01C7L << 0L;
	pcAssesser->AddPacket(WORLD_SERVER,cmActionComplete,4);
}