www.pudn.com > uoth_src.zip > Character.cpp


//----------------------------------------------------------------------------- 
//  
// @doc 
// 
// @module	Character.cpp - Character information class | 
// 
// This module contains the Character information class. 
// 
// Copyright (c) 2002 - Descartes Systems Sciences, Inc. 
// 
// All rights reserved. 
// 
// Redistribution and use in source and binary forms, with or without  
// modification, are permitted provided that the following conditions are  
// met: 
//  
// 1. Redistributions of source code must retain the above copyright notice,  
//    this list of conditions and the following disclaimer.  
// 2. Neither the name of Descartes Systems Sciences, Inc nor the names of  
//    its contributors may be used to endorse or promote products derived  
//    from this software without specific prior written permission. 
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT  
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR  
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED  
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR  
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING  
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS  
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
// 
// @end 
// 
// $History: Cnf.cpp $ 
//       
//----------------------------------------------------------------------------- 
 
#include "stdafx.h" 
#include "Character.h" 
#include "DataParser.h" 
#include "uoth.h" 
 
// 
// Debug NEW 
// 
 
#if defined (_DEBUG) 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
// 
// Class globals 
// 
 
CAtlArray  CCharacter::gm_vCharacters; 
 
// 
// Externals 
// 
 
extern HWND g_hWndMain; 
extern TCHAR g_szSettingsFile []; 
 
// 
// Locals 
// 
 
static int s_nCurrent = -1; 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc  constructor. 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
CCharacter::CCharacter () 
{ 
	Init (true); 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc  destructor. 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
CCharacter::~CCharacter () 
{ 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Initialize the object 
// 
// @parm bool | fConstruct | If true, we are being called from the 
//		the constructor 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CCharacter::Init (bool fConstruct) 
{ 
	m_strName .Empty (); 
	m_vMapCounts .RemoveAll (); 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Begin the processing of a Character 
// 
// @parm CDataParser * | pParser | Current parser 
// 
// @parm const XML_Char ** | papszAttrs | Attributes 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CCharacter::OnStart (CDataParser *pParser, const XML_Char **papszAttrs) 
{ 
 
	// 
	// No attributes are allowed 
	// 
 
	if (papszAttrs [0] != NULL) 
	{ 
		pParser ->SetError (IDS_ERR_XML_NO_ATTRS); 
		return; 
	} 
 
	// 
	// Initialize the Character 
	// 
 
	Init (false); 
 
	// 
	// Move to the new state 
	// 
 
	pParser ->SetState (CDataParser::InCharacter); 
	return; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Begin the processing of an XML element 
// 
// @parm CDataParser * | pParser | Current parser 
// 
// @parm const XML_Char * | pszName | Name of the element 
// 
// @parm const XML_Char ** | papszAttrs | Attributes 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CCharacter::OnStartElement (CDataParser *pParser,  
	const XML_Char *pszName, const XML_Char **papszAttrs) 
{ 
	// 
	// Get the element 
	// 
 
	_Element nElement = GetElement (pszName); 
	if (nElement == Unknown) 
	{ 
		pParser ->SetError (IDS_ERR_XML_UNEXPECTED_ELEMENT); 
		return; 
	} 
 
	// 
	// If this is a map count 
	// 
 
	if (nElement == MapCounts) 
	{ 
		// 
		// The only allowed attribute is Index and 
		// it is required 
		// 
 
		if (papszAttrs [0] == NULL || 
			strcmp (papszAttrs [0], "Index") != 0 || 
			papszAttrs [2] != NULL) 
		{ 
			pParser ->SetError (IDS_ERR_XML_ONLY_INDEX); 
			return; 
		} 
 
		// 
		// Get the index number 
		//  
 
		int nIndex = atol (papszAttrs [1]); 
 
		// 
		// Validate the treasure range 
		// 
 
		if (nIndex <= 0 || nIndex > CTreasure::Max_Treasure) 
		{ 
			pParser ->SetError (IDS_ERR_XML_INDEX_RANGE); 
			return; 
		} 
 
		// 
		// Save the index 
		// 
 
		pParser ->m_nMapIndex = nIndex; 
	} 
 
	// 
	// Otherwise 
	// 
 
	else 
	{ 
 
		// 
		// No attributes are allowed 
		// 
 
		if (papszAttrs [0] != NULL) 
		{ 
			pParser ->SetError (IDS_ERR_XML_NO_ATTRS); 
			return; 
		} 
	} 
	return; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc End an XML element 
// 
// @parm CDataParser * | pParser | Current parser 
// 
// @parm const XML_Char * | pszName | Name of the element 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CCharacter::OnEndElement (CDataParser *pParser, const XML_Char *pszName) 
{ 
 
	// 
	// Get the element 
	// 
 
	_Element nElement = GetElement (pszName); 
	if (nElement == Unknown) 
	{ 
		pParser ->SetError (IDS_ERR_XML_UNEXPECTED_ELEMENT); 
		return; 
	} 
 
	// 
	// Switch based on the element 
	// 
 
	switch (nElement) 
	{ 
		 
		// 
		// If we are ending the Character 
		// 
 
		case Character: 
			pParser ->SetState (CDataParser::InData); 
			gm_vCharacters .Add (*this); 
			break; 
 
		// 
		// If this is the name 
		// 
 
		case Name: 
			m_strName = pParser ->GetText (false); 
			break; 
 
		// 
		// If this is the map counts 
		// 
 
		case MapCounts: 
			{ 
				CMapCounts mc; 
				mc .m_nIndex = pParser ->m_nMapIndex; 
				XML_Char *psz = pParser ->GetText (true); 
				int i = 0; 
				while (psz && *psz && i < Max_Level) 
				{ 
					XML_Char *pszComma = strchr (psz, ','); 
					if (pszComma) 
						*pszComma++ = 0; 
					mc .m_anCounts [i++] = atol (psz); 
					psz = pszComma; 
				} 
				while (i < Max_Level) 
					mc .m_anCounts [i++] = 0; 
				m_vMapCounts .Add (mc); 
			} 
			break; 
	} 
	return; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Get the element number 
// 
// @parm const XML_Char * | pszName | Element name 
// 
// @rdesc Element id. 
// 
//----------------------------------------------------------------------------- 
 
CCharacter::_Element CCharacter::GetElement (const XML_Char *pszName) 
{ 
	if (stricmp (pszName, "Character") == 0) 
		return Character; 
	else if (stricmp (pszName, "Name") == 0) 
		return Name; 
	else if (stricmp (pszName, "MapCounts") == 0) 
		return MapCounts; 
	else 
		return Unknown; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Locate a map count for the given treasure 
// 
// @parm int | nIndex | Treasure index 
// 
// @rdesc Pointer to the map count or NULL if not found 
// 
//----------------------------------------------------------------------------- 
 
CMapCounts *CCharacter::FindMapCounts (int nIndex) 
{ 
	for (int imc = 0; imc < m_vMapCounts .GetCount (); ++imc) 
	{ 
		if (m_vMapCounts [imc] .m_nIndex == nIndex) 
			return &m_vMapCounts [imc]; 
	} 
	return NULL; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Locate a character 
// 
// @parm LPCTSTR | pszName | Name of the character 
// 
// @rdesc Pointer to the character or NULL if not found 
// 
//----------------------------------------------------------------------------- 
 
CCharacter *CCharacter::Find (LPCTSTR pszName) 
{ 
	for (int ic = 0; ic < gm_vCharacters .GetCount (); ++ic) 
	{ 
		if (_tcsicmp (gm_vCharacters [ic] .m_strName, pszName) == 0) 
			return &gm_vCharacters [ic]; 
	} 
	return NULL; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Add a character 
// 
// @parm LPCTSTR | pszName | Name of the character 
// 
// @rdesc Pointer to the character  
// 
//----------------------------------------------------------------------------- 
 
CCharacter *CCharacter::Add (LPCTSTR pszName) 
{ 
 
	// 
	// Try to find the character 
	// 
 
	CCharacter *pCharacter = Find (pszName); 
	if (pCharacter != NULL)  
		return pCharacter; 
 
	// 
	// Create a new character 
	// 
 
	CCharacter c; 
	c .m_strName = pszName; 
	gm_vCharacters .Add (c); 
	pCharacter = &gm_vCharacters [gm_vCharacters .GetCount () - 1]; 
	return pCharacter; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Adjust teh count of a treasure 
// 
// @parm int | nTreasure | Treasure number 
// 
// @parm int | nLevel | Treasure level 
// 
// @parm bool | fAdd | If true, we are adding 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CCharacter::AdjustCount (int nTreasure, int nLevel, bool fAdd) 
{ 
 
	// 
	// Locate the counts 
	// 
 
	CMapCounts *pCounts = FindMapCounts (nTreasure); 
 
	// 
	// If not found 
	// 
 
	if (pCounts == NULL) 
	{ 
		if (fAdd) 
		{ 
			CMapCounts c; 
			memset (&c, 0, sizeof (c)); 
			c .m_nIndex = nTreasure; 
			c .m_anCounts [nLevel - 1] = 1; 
			m_vMapCounts .Add (c); 
		} 
	} 
 
	// 
	// If found 
	// 
 
	else 
	{ 
		if (fAdd) 
		{ 
			pCounts ->m_anCounts [nLevel - 1]++; 
		} 
		else if (pCounts ->m_anCounts [nLevel - 1] > 0) 
		{ 
			pCounts ->m_anCounts [nLevel - 1]--; 
		} 
	} 
 
	// 
	// Reset the has map 
	// 
 
	ApplyFilter (); 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Write to a stream 
// 
// @parm FILE * | fp | Output file 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CCharacter::Write (FILE *fp) 
{ 
	fprintf (fp, "\t\n"); 
	fprintf (fp, "\t\t%s\n", (LPCTSTR) m_strName); 
	for (int imc = 0; imc < m_vMapCounts .GetCount (); ++imc) 
	{ 
		CMapCounts *pMapCounts = &m_vMapCounts [imc]; 
		int nMax = GetMaxLevel (pMapCounts); 
		if (nMax > 0) 
		{ 
			fprintf (fp, "\t\t", pMapCounts ->m_nIndex); 
			for (int i = 0; i < nMax; i++) 
			{ 
				if (i != 0) 
					fputc (',', fp); 
				fprintf (fp, "%d", pMapCounts ->m_anCounts [i]); 
			} 
			fprintf (fp, "\n"); 
		} 
	} 
	fprintf (fp, "\t\n"); 
	return; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Get the max level for this count 
// 
// @parm CMapCounts * | pCounts | Pointer to the map counts structure 
// 
// @rdesc Index of the max level or zero for none 
// 
//----------------------------------------------------------------------------- 
 
int CCharacter::GetMaxLevel (CMapCounts *pCounts) 
{ 
	int nMax = 0; 
	for (int i = 0; i < Max_Level; i++) 
	{ 
		if (pCounts ->m_anCounts [i] > 0) 
			nMax = i + 1; 
	} 
	return nMax; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Return the current character 
// 
// @rdesc Pointer to the current character or NULL if there is none 
// 
//----------------------------------------------------------------------------- 
 
CCharacter *CCharacter::GetCurrent () 
{ 
	if (s_nCurrent >= 0) 
        return &gm_vCharacters [s_nCurrent]; 
	else 
		return NULL; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Set the current character  
// 
// @parm CCharacter * | pCharacter | Pointer to the character 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CCharacter::SetCurrent (CCharacter *pCharacter) 
{ 
 
	// 
	// Set the character 
	// 
 
	s_nCurrent = pCharacter - &gm_vCharacters [0]; 
	 
	// 
	// Reset the has maps 
	// 
 
	ApplyFilter (); 
 
	// 
	// Save the setting 
	// 
 
	::WritePrivateProfileString (PROFILE_SETTINGS, PROFILE_CHARACTER,  
		pCharacter ? (LPCTSTR) pCharacter ->m_strName : _T ( ""),  
		g_szSettingsFile); 
	return; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Get the default character from the profile 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CCharacter::GetDefaultCurrent () 
{ 
 
	// 
	// Get the current character 
	// 
 
	TCHAR szText [256]; 
	::GetPrivateProfileString (PROFILE_SETTINGS, PROFILE_CHARACTER, 
		_T ( ""), szText, _countof (szText), g_szSettingsFile); 
	szText [_countof (szText) - 1] = 0; 
 
	// 
	// Locate the character 
	// 
 
	CCharacter *pCharacter = Find (szText); 
 
	// 
	// Based on the results of the find, select the default 
	// 
 
	if (pCharacter == NULL) 
	{ 
		if (gm_vCharacters .GetCount () > 0) 
			s_nCurrent = 0; 
		else 
			s_nCurrent = -1; 
	} 
	else 
		s_nCurrent = pCharacter - &gm_vCharacters [0]; 
	ApplyFilter (); 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Delete a character 
// 
// @parm CCharacter * | pCharacter | Character to delete.  This address 
//		must be within the array of characters. 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CCharacter::Delete (CCharacter *pCharacter) 
{ 
 
	// 
	// Adjust the current index 
	// 
 
	int nDelete = pCharacter - &gm_vCharacters [0]; 
	if (s_nCurrent < nDelete) 
		; 
	else if (s_nCurrent == nDelete) 
		s_nCurrent = -1; 
	else  
		s_nCurrent--; 
 
	// 
	// Delete the character 
	// 
 
	gm_vCharacters .RemoveAt (nDelete); 
 
	// 
	// Update the current 
	// 
 
	SetCurrent (GetCurrent ()); 
}