/*
* 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 cCovenantCrystal.cpp
 *	Implements functionality for covenant crystals.
 *
 *	This class is referenced whenever a covenant crystal 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 covenant crystals.
 *
 *	Called whenever a covenant crystal object should be initialized.
 */
cCovenant::cCovenant( WORD type, DWORD dwGUID, DWORD dwHouseID, char *szName, char *szDescription, cLocation *pcLoc )
{
	SetLocation( pcLoc );
	m_dwGUID = dwGUID;
	m_dwHouseID = dwHouseID;
	m_strName.assign( szName );
	m_strDescription.assign( szDescription );
	m_dwModel = type;
	m_fStatic = TRUE;
}

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

/**
 *	Handles the message sent for the creation of covenant crystals in the world.
 *
 *	This function is called whenever a covenant crystal should be created in the world for a client.
 *
 *	@return cMessage - Returns a Create Object (0x0000F745) server message.
 */
cMessage cCovenant::CreatePacket()
{
	cMessage cmCreate;
	
	char	szCommand[200];
	RETCODE	retcode;
	
	char	OwnerIDBuff[9];
	DWORD	OwnerID = NULL;

	char	szName[75];
	std::string		strName = m_strName;

	sprintf( szCommand, "SELECT OwnerID FROM houses_covenants WHERE HouseID = %d;",m_dwHouseID);
	retcode = SQLPrepare( cDatabase::m_hStmt, (unsigned char *)szCommand, SQL_NTS );			CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
	retcode = SQLExecute( cDatabase::m_hStmt );
	
	retcode = SQLBindCol( cDatabase::m_hStmt, 1, SQL_C_CHAR, OwnerIDBuff, sizeof( OwnerIDBuff ), NULL );	CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, 1)

	if (SQLFetch( cDatabase::m_hStmt ) == SQL_SUCCESS) {		
		sscanf(OwnerIDBuff,"%08x",&OwnerID);

		retcode = SQLCloseCursor( cDatabase::m_hStmt );					CHECKRETURN(0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
		retcode = SQLFreeStmt( cDatabase::m_hStmt, SQL_UNBIND );

		sprintf( szCommand, "SELECT Name FROM avatar WHERE AvatarGUID = %08x;",OwnerID);
		retcode = SQLPrepare( cDatabase::m_hStmt, (unsigned char *)szCommand, SQL_NTS );			CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
		retcode = SQLExecute( cDatabase::m_hStmt );
	
		retcode = SQLBindCol( cDatabase::m_hStmt, 1, SQL_C_CHAR, szName, sizeof( szName ), NULL );					CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, 1)

		// Return SQL_SUCCESS if there is a player that corresponds to owner of the fetched covenant crystal
		if (SQLFetch( cDatabase::m_hStmt ) == SQL_SUCCESS) {
		
			std::string		str1 = szName;
  			strName.assign(str1 + "'s " + m_strName);
		}
	}
	retcode = SQLCloseCursor( cDatabase::m_hStmt );					CHECKRETURN(0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
	retcode = SQLFreeStmt( cDatabase::m_hStmt, SQL_UNBIND );

	float	flpScale;				// Scale used in Packet being Sent
	float	flmScale = 0;			// Model Data Scale
	DWORD	dwFlags1 = 0x00018003;  // Flags1

	if (WORD(m_wModel) != 0x3CF8) {	// if not apartment (cottages, villas, mansions)
		flmScale = 1.2f;
		dwFlags1 += 0x00000080L;	// mask 'floatscale' if cottage, villa, or mansion
	}
/*
AnimConfig
0x00B8L	cottages,villas,mansions
0x00EAL	apartment

dwModel
0x0AAFL	cottages,villas,mansions
0x0C7AL	apartment

wModelID		
0x2DC2	mansion
0x2ECC	villa
0x2DC5	villa	
0x5173	cottage
0x3CF8	apartment

wIconID
0x218C
*/
	cmCreate	<< 0xF745L 
				<< m_dwGUID 
				<< BYTE( 0x11 ) 
				<< BYTE( 0 ) 
				<< BYTE( 0 ) 
				<< BYTE( 0 );

	cmCreate << dwFlags1;

	cmCreate << 0x00000414;	// Type of portal (0x0410 = solid; 0x0414 = not solid?)
	

	// Flags1 Mask: 0x00018003 or 0x00018083
	{
		// Flags1 & 0x00100000 -- Unknown Count
		DWORD dwUnkCount = 0x0000000C;

		BYTE ownedByte;
		if (OwnerID) {
			ownedByte = 0x0B;
		} else {
			ownedByte = 0x0A;
		}
		BYTE unknownByte[0x0C] = {	0x00,0x00,0x3D,0x00,0x02,0x00,0x00,0x00,
									ownedByte, // model appearance:  owned = 0x0B; unowned = 0x0A, 0x0C?
									0x00,0x00,0x00};
		cmCreate << dwUnkCount;
			
		for ( int i = 0; i < dwUnkCount; ++i ) {
			cmCreate << unknownByte[i];
		}
		DWORD dwUnknownDword = 0x0L;
		cmCreate << dwUnknownDword;
		
		// Flags1 & 0x00008000 -- Location 
		cmCreate.pasteData( (UCHAR*)&m_Location, sizeof(m_Location) );	// the location

		//Flags1 & 0x0000002 -- DWORD ResourceID Animations
		DWORD dwAnimC = 0x09000000L + m_wAnimConfig;
		cmCreate << dwAnimC;

		// Flags1 & 0x00000001 -- DWORD dwModel = 0x02000001; // the model.
		DWORD dwModel = 0x02000000L + m_dwModel;
		cmCreate << dwModel;

		if (WORD(m_wModel) != 0x3CF8)
		{
			//Flags1 & 0x00000080 -- unknown_green
			if (flmScale > 0)
			{
				flpScale = flmScale;	// FLOAT flpScale
			}
			else
			{
				flpScale = 1.0;
			}
			cmCreate << flpScale;
		}
	}

	// SeaGreens
	WORD wUnkFlag2 = 0x0004;
	WORD wUnkFlag3 = 0x0000;
	WORD wUnkFlag4 = 0x0000;
	WORD wUnkFlag6 = 0x0004; // always seems same as wUnkFlag2
	WORD wUnkFlag7 = 0x0000;
	WORD wUnkFlag8 = 0x0000;
	WORD wUnkFlag10 = 0x0000;

	cmCreate	<< m_wPositionSequence	// movement 0x0001
				<< wUnkFlag2			// animations
				<< wUnkFlag3			// bubble modes
				<< wUnkFlag4			// num jumps
				<< m_wNumPortals 
				<< wUnkFlag6			// anim count
				<< wUnkFlag7			// overrides
				<< wUnkFlag8
				<< WORD(0x0D7F)			// m_wNumLogins // 0x0D4B
				<< wUnkFlag10;

	
	DWORD dwFlags2 = 0x0030L;		// Flags2 -- Defines what data comes next
	if (m_dwOwnerID) {
		dwFlags2 += 0x02000000L;	// mask 'houseOwnerID' if owned
	}

	cmCreate << dwFlags2;
	
	cmCreate << strName.c_str();	// Object's Name
	
	cmCreate << WORD(m_wModel) << WORD(m_wIcon);

	DWORD dwObjectFlags1 = 0x00000000; // 0x0080 -- Miscellaneous Object
	DWORD dwObjectFlags2 = 0x00001014; // 0x0004 -- Cannot be picked up; 0x0010 -- Can be selected

	cmCreate << dwObjectFlags1 << dwObjectFlags2;

	// Flags2 & 0x00000010
	DWORD dwunknown_v2 = 0x00000020; // Value
	cmCreate << dwunknown_v2;

	// Flags2 & 0x00000020
	float flApproach = 3.0f; 
	cmCreate << flApproach;

	if (OwnerID) {
		// Flags2 & 0x02000000
		cmCreate << OwnerID;
	}
	return cmCreate;
}

/**
 *	Handles the actions of covenant crystal objects.
 *
 *	This function is called whenever a covenant crystal is used or should perform an action.
 */
void cCovenant::Action(cClient* who)
{
	cMessage cmUseCrystal;

	char	szCommand[200];
	RETCODE	retcode;
	
	char	OwnerIDBuff[9];
	DWORD	OwnerID = NULL;
	char	HouseGUIDBuff[9];
	DWORD	HouseGUID = NULL;

	char	szName[75];
	std::string		strPlayerName = "";

	sprintf( szCommand, "SELECT OwnerID,GUID FROM houses WHERE wModel = %d;",m_dwHouseID);
	retcode = SQLPrepare( cDatabase::m_hStmt, (unsigned char *)szCommand, SQL_NTS );			CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
	retcode = SQLExecute( cDatabase::m_hStmt );
	
	retcode = SQLBindCol( cDatabase::m_hStmt, 1, SQL_C_CHAR, OwnerIDBuff, sizeof( OwnerIDBuff ), NULL );	CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, 1)
	retcode = SQLBindCol( cDatabase::m_hStmt, 2, SQL_C_CHAR, HouseGUIDBuff, sizeof( HouseGUIDBuff ), NULL );	CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, 1)

	// Return SQL_SUCCESS if there is a house that corresponds to the covenant crystal
	if (SQLFetch( cDatabase::m_hStmt ) == SQL_SUCCESS) {
		
		sscanf(OwnerIDBuff,"%08x",&OwnerID);
		sscanf(HouseGUIDBuff,"%08x",&HouseGUID);

		retcode = SQLCloseCursor( cDatabase::m_hStmt );					CHECKRETURN(0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
		retcode = SQLFreeStmt( cDatabase::m_hStmt, SQL_UNBIND );


		sprintf( szCommand, "SELECT Name FROM avatar WHERE AvatarGUID = %08x;",OwnerID);
		retcode = SQLPrepare( cDatabase::m_hStmt, (unsigned char *)szCommand, SQL_NTS );			CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
		retcode = SQLExecute( cDatabase::m_hStmt );
	
		retcode = SQLBindCol( cDatabase::m_hStmt, 1, SQL_C_CHAR, szName, sizeof( szName ), NULL );					CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, 1)

		// Return SQL_SUCCESS if there is a player that corresponds to owner of the fetched house
		if (SQLFetch( cDatabase::m_hStmt ) == SQL_SUCCESS) {
			std::string		str1 = szName;
  			strPlayerName.assign(str1);
		}
		retcode = SQLCloseCursor( cDatabase::m_hStmt );					CHECKRETURN(0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
		retcode = SQLFreeStmt( cDatabase::m_hStmt, SQL_UNBIND );
	} else {
		retcode = SQLCloseCursor( cDatabase::m_hStmt );					CHECKRETURN(0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
		retcode = SQLFreeStmt( cDatabase::m_hStmt, SQL_UNBIND );
	}

	cmUseCrystal<< 0xF74CL					// Packet type
				<< who->m_pcAvatar->GetGUID()	// Character's GUID
				<< m_wNumLogins				// number of logins
				<< ++m_wPositionSequence	// sequence number
				<< ++m_wNumAnims			// Number Animations this login session
				<< WORD(0x00)				// Activity
				<< WORD(0x06)
				<< WORD(0x3D)				// Starting Stance
				<< m_dwGUID;					// Covenant Crystals's GUID
				cmUseCrystal.pasteData( (UCHAR*)&m_Location, sizeof(m_Location) ); // Covenant Crystals' location
	cmUseCrystal<< 0x19C5EE4F				// bitfield?
				<< 0x40400000				// float1 -- unknown float
				<< 0x00000000				// float2 -- unknown float
				<< 0x7F7FFFFF				// unknown3 -- unknown DWORD
				<< 0x3F800000				// speed (1)
				<< 0x41700000				// float4 -- unknown float
				<< 0x00000000				// heading
				<< 0x3F800000;				// unknown -- unknown DWORD
	
	cWorldManager::SendToAllInFocus( who->m_pcAvatar->m_Location, cmUseCrystal, 3 );

	// eLeM:  Display Dwelling Purchase/Maintenance Panel

	int i;
	cMessage cmDisplayPanel;
	cmDisplayPanel << 0xF7B0L << who->m_pcAvatar->GetGUID( ) << ++who->m_dwF7B0Sequence << 0x021DL 
	<< m_dwGUID;			// Covenant Crystal's GUID

	DWORD ownerType =		0x00000001;	// Self = 0x00000001; Allegiance = 0x00000003
	DWORD levelReq =		0x00000001;	// Apartment, Cottage = 0x00000014; Villa = 0x00000023; Mansion = 0x00000032
	DWORD unknown2 =		0xFFFFFFFF;
	DWORD rankReq =			0xFFFFFFFF;	// Apartment, Cottage, Villa = 0xFFFFFFFF; Mansion = 0x00000006
	DWORD unknown3 =		0xFFFFFFFF;
	DWORD unknown4 =		0x00000000;
	DWORD unknown5 =		0x00000001;
	DWORD ownerName=		0x00000000;
	DWORD purchaseCount =	0x00000001;	// Apartment = 2; Cottage, Villa = 3; Mansion = 6;
		
	cmDisplayPanel	<< HouseGUID	// Dwelling ID
					<< OwnerID		// Dwelling Owner ID (NULL == 0x00000000)
					<< ownerType
					<< levelReq			// level requirement to purchase this dwelling (-1 if no requirement)
					<< unknown2
					<< rankReq			// rank requirement to purchase this dwelling (-1 if no requirement)
					<< unknown3
					<< unknown4
//					<< unknown5
					<< strPlayerName.c_str();		// name of the current owner (NULL == 0x00000000)

	/* Item type:
	0x00000111 = Pyreal
	0x00002DBE = Writ of Refuge / Writs of Refuge
	0x00001086 = Mattekar Hide Sleeves
	0x00000E74 = Gold Phyntos Wasp Wing
	0x00002527 = Golden Gromnie
	0x000021FD = A Lucky Gold Letter
	0x000024C5 = Dread Mattekar Paw
	*/
	DWORD dwPurchaseCount;	// Apartment = 2; Cottage, Villa = 3; Mansion = 6;
	sprintf( szCommand, "SELECT COUNT(ID) FROM houses_purchase WHERE HouseID = %d;",m_dwHouseID );
	retcode = SQLPrepare( cDatabase::m_hStmt, (BYTE *)szCommand, SQL_NTS );	CHECKRETURN( 1, SQL_HANDLE_STMT, cDatabase::m_hStmt, 1 )
	retcode = SQLExecute( cDatabase::m_hStmt );								CHECKRETURN( 1, SQL_HANDLE_STMT, cDatabase::m_hStmt, 1 )
	retcode = SQLBindCol( cDatabase::m_hStmt, 1, SQL_C_ULONG, &dwPurchaseCount, sizeof( dwPurchaseCount ), NULL );	CHECKRETURN( 1, SQL_HANDLE_STMT, cDatabase::m_hStmt, 1 )
	retcode = SQLFetch( cDatabase::m_hStmt );
	if( retcode == SQL_NO_DATA )
		dwPurchaseCount = 0;
	retcode = SQLCloseCursor( cDatabase::m_hStmt );				CHECKRETURN( 0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL )
	retcode = SQLFreeStmt( cDatabase::m_hStmt, SQL_UNBIND );	CHECKRETURN( 0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL )	
	cmDisplayPanel << dwPurchaseCount;		// the number of items required to purchase this dwelling

	/* Item type:
	0x00000111 = Pyreal
	0x00002DBE = Writ of Refuge / Writs of Refuge
	0x00001086 = Mattekar Hide Sleeves
	0x00000E74 = Gold Phyntos Wasp Wing
	0x00002527 = Golden Gromnie
	0x000021FD = A Lucky Gold Letter
	0x000024C5 = Dread Mattekar Paw
	*/

	/* Purchase Amount:
	Apartment:
	0x000186A0	100,000 Pyreal
	0x00000001	1 Writ of Refuge

	Cottage:
	0x000493E0	300,000 Pyreal
	0x00000001	1 Writ of Refuge
		Other Item:
		0x00000001	1 Mattekar Hide Sleeves

	Villa:
	0x001E8480	2,000,000 Pyreal
	0x00000005	5 Writs of Refuge
		Other Item:
		0x00000001	1 Gold Phyntos Wasp Wing

	Mansion:
	0x00989680	10,000,000 Pyreal
	0x00000014	20 Writs of Refuge
		Other Items:
		0x00000014	20 Golden Gromnie
		0x0000000F	15 A Lucky Gold Letter
		0x00000002	2 Dread Mattekar Paw
	*/
	DWORD	dwBuyType;
	DWORD	dwBuyRequired;
	DWORD	dwBuyPaid;
//	String	buyName;
//	String	buyPluralName;

	sprintf( szCommand, "SELECT ItemLinker,Required,Paid FROM houses_purchase WHERE HouseID = %d;",m_dwHouseID );														
	retcode = SQLPrepare( cDatabase::m_hStmt, (BYTE *)szCommand, SQL_NTS );	CHECKRETURN( 1, SQL_HANDLE_STMT, cDatabase::m_hStmt, 1 )
	retcode = SQLExecute( cDatabase::m_hStmt );								CHECKRETURN( 1, SQL_HANDLE_STMT, cDatabase::m_hStmt, 1 )
	retcode = SQLBindCol( cDatabase::m_hStmt, 1, SQL_C_ULONG, &dwBuyType, sizeof( dwBuyType ), NULL );				CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, 1)
	retcode = SQLBindCol( cDatabase::m_hStmt, 2, SQL_C_ULONG, &dwBuyRequired, sizeof( dwBuyRequired ), NULL );		CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
	retcode = SQLBindCol( cDatabase::m_hStmt, 3, SQL_C_ULONG, &dwBuyPaid, sizeof( dwBuyPaid ), NULL );				CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)

	for ( i = 0; SQLFetch( cDatabase::m_hStmt ) == SQL_SUCCESS; ++i ) {
		if( retcode == SQL_NO_DATA ) {
			dwBuyRequired = 1;
			dwBuyPaid = 0;
			dwBuyType = 12;
		}
		cItemModels *pcModel = cItemModels::FindModel(dwBuyType);
		std::string		strPluralName = pcModel->m_strName.c_str();
  		strPluralName.assign(strPluralName + "s");

		cmDisplayPanel	<< dwBuyRequired				// quantity required
						<< dwBuyPaid					// quantity paid
						<< DWORD(pcModel->m_wModel)		// item's object type
						<< pcModel->m_strName.c_str()	// name of this item
						<< strPluralName.c_str();		// plural name of this item (if not specified, use <name> followed by 's' or 'es')
	}
	retcode = SQLCloseCursor( cDatabase::m_hStmt );				CHECKRETURN(0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
	retcode = SQLFreeStmt( cDatabase::m_hStmt, SQL_UNBIND );

	DWORD dwMaintenanceCount;		// Apartment, Cottage = 1; Villa, Mansion = 2;
	sprintf( szCommand, "SELECT COUNT(ID) FROM houses_maintenance WHERE HouseID = %d;",m_dwHouseID );
	retcode = SQLPrepare( cDatabase::m_hStmt, (BYTE *)szCommand, SQL_NTS );	CHECKRETURN( 1, SQL_HANDLE_STMT, cDatabase::m_hStmt, 1 )
	retcode = SQLExecute( cDatabase::m_hStmt );								CHECKRETURN( 1, SQL_HANDLE_STMT, cDatabase::m_hStmt, 1 )
	retcode = SQLBindCol( cDatabase::m_hStmt, 1, SQL_C_ULONG, &dwMaintenanceCount, sizeof( dwMaintenanceCount ), NULL );	CHECKRETURN( 1, SQL_HANDLE_STMT, cDatabase::m_hStmt, 1 )
	retcode = SQLFetch( cDatabase::m_hStmt );
	if( retcode == SQL_NO_DATA )
		dwMaintenanceCount = 0;
	retcode = SQLCloseCursor( cDatabase::m_hStmt );				CHECKRETURN( 0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL )
	retcode = SQLFreeStmt( cDatabase::m_hStmt, SQL_UNBIND );	CHECKRETURN( 0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL )	
	cmDisplayPanel << dwMaintenanceCount;	// the number of items required to pay the maintenance cost for this dwelling

	/* Maintenance Amount:
	Apartment:
	0x00002710	10,000 Pyreal

	Cottage:
	0x00007530	30,000 Pyreal

	Villa:
	0x000186A0	100,000 Pyreal
	0x00000002	2 Writs of Refuge

	Mansion:
	0x000F4240	1,000,000 Pyreal
	0x00000010	10 Writs of Refuge
	*/				
	DWORD	dwMaintainType;
	DWORD	dwMaintainRequired;
	DWORD	dwMaintainPaid;
//	String	maintainName;
//	String	maintainPluralName;	
	
	sprintf( szCommand, "SELECT ItemLinker,Required,Paid FROM houses_maintenance WHERE HouseID = %d;",m_dwHouseID );														
	retcode = SQLPrepare( cDatabase::m_hStmt, (BYTE *)szCommand, SQL_NTS );	CHECKRETURN( 1, SQL_HANDLE_STMT, cDatabase::m_hStmt, 1 )
	retcode = SQLExecute( cDatabase::m_hStmt );								CHECKRETURN( 1, SQL_HANDLE_STMT, cDatabase::m_hStmt, 1 )
	retcode = SQLBindCol( cDatabase::m_hStmt, 1, SQL_C_ULONG, &dwMaintainType, sizeof( dwMaintainType ), NULL );				CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, 1)
	retcode = SQLBindCol( cDatabase::m_hStmt, 2, SQL_C_ULONG, &dwMaintainRequired, sizeof( dwMaintainRequired ), NULL );		CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
	retcode = SQLBindCol( cDatabase::m_hStmt, 3, SQL_C_ULONG, &dwMaintainPaid, sizeof( dwMaintainPaid ), NULL );				CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)

	for ( i = 0; SQLFetch( cDatabase::m_hStmt ) == SQL_SUCCESS; ++i ) {
		if( retcode == SQL_NO_DATA ) {
			dwMaintainRequired = 1;
			dwMaintainPaid = 0;
			dwMaintainType = 12;
		}
		cItemModels *pcModel = cItemModels::FindModel(dwMaintainType);
		std::string		strPluralName = pcModel->m_strName.c_str();
  		strPluralName.assign(strPluralName + "s");

		cmDisplayPanel	<< dwMaintainRequired			// quantity required
						<< dwMaintainPaid				// quantity paid
						<< DWORD(pcModel->m_wModel)		// item's object type
						<< pcModel->m_strName.c_str()	// name of this item
						<< strPluralName.c_str();		// plural name of this item (if not specified, use <name> followed by 's' or 'es')
	}
	retcode = SQLCloseCursor( cDatabase::m_hStmt );				CHECKRETURN(0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
	retcode = SQLFreeStmt( cDatabase::m_hStmt, SQL_UNBIND );

	who->AddPacket(WORLD_SERVER,cmDisplayPanel,4);

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

/**
 *	Handles the assessment of covenant crystal objects.
 *
 *	This function is called whenever a covenant crystal is assessed by a client.
 *
 *	Returns a Game Event (0x0000F7B0) server message of type Identify Object (0x000000C9).
 */
void cCovenant::Assess(cClient *pcAssesser)
{
	// eLeM:  Covenant Crystal assess

	//	cObject *pcObject = cWorldManager::FindObject( m_dwGUID );
	cMessage cmAssess;
	DWORD flags = 0x00000008;
	m_strDescription.assign(m_dwMode ? "The current maintenance has not been paid." : "The current maintenance has been paid.");

	WORD length = (m_dwMode ? 0x002B : 0x0027);
	cmAssess << 0xF7B0L << pcAssesser->m_pcAvatar->GetGUID() << ++pcAssesser->m_dwF7B0Sequence << 0xC9L << m_dwGUID
	<< flags
	<< 0x01L						// Success = 0x01, Failure = 0x00
	<< WORD(0x0001)					// Total number of DWORDS
	<< WORD(0x0008)					// Unknown
	<< 0x10L
	<< 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);
}