//------------------------------------------------------------------------------------------------------
//
//  FUNCTION:   LoadCivXml(FXml* pFXml, TCHAR* szFilename)
//
//  PURPOSE :   Gets the full pathname for the xml file from the FileManager .
//				If it is succesful we return true
//				from the function and a valid FXml pointer to the pFXml parameter.
//
//------------------------------------------------------------------------------------------------------
bool CvXMLLoadUtility::LoadCivXml(FXml* pFXml, const TCHAR* szFilename)
{
	char szLog[256];
	sprintf(szLog, "LoadCivXml (%s)", szFilename);
	PROFILE(szLog);
	OutputDebugString(szLog);
	OutputDebugString("\n");

	CvString szPath = szFilename;
	CvString fsFilename = szFilename;

	if (!gDLL->fileManagerEnabled())
	{
		szPath = "Assets//" + szPath;
	}

	logMsg("Loading XML file %s\n", szPath.c_str());

	if (!gDLL->getXMLIFace()->LoadXml(pFXml, szPath))
	{
		logMsg("Load XML file %s FAILED\n", szPath.c_str());
		return false;
	}

	logMsg("Load XML file %s SUCCEEDED\n", szPath.c_str());
	GC.setCurrentXMLFile(szFilename);
	return true;	// success
}
/// Helper function to read a single type (as a string) and find its ID in a database table.
/// Assumes the type is in the table's field "Type"
int ReadDBLookup(FDataStream& kStream, const char* szTable, bool* bValid /*= NULL*/)
{
	FStringFixedBuffer(sTemp, 256);
	kStream >> sTemp;
	if (bValid) *bValid = true;
	if(sTemp.GetLength() > 0 && sTemp != "NO_TYPE")
	{
		Database::Connection* pDB = GC.GetGameDatabase();
		if(pDB)
		{
			Database::Results kResults;
			CvString szCommand;
			szCommand.Format("SELECT ID from %s where Type = ? LIMIT 1", szTable);
			if(pDB->Execute(kResults, szCommand.c_str()))
			{
				kResults.Bind(1, sTemp.c_str());
				if(kResults.Step())
				{
					return kResults.GetInt(0);
				}
				else
					if (bValid) *bValid = false;
			}
		}
		else
			if (bValid) *bValid = false;
	}
	
	return -1;
}
Example #3
0
/// Logging function to write out info on Ideology choices
void CvPolicyAI::LogIdeologyChoice(CvString &decisionState, int iWeightFreedom, int iWeightAutocracy, int iWeightOrder)
{
    if(GC.getLogging() && GC.getAILogging())
    {
        CvString strOutBuf;
        CvString strBaseString;
        CvString strTemp;
        CvString playerName;

        // Find the name of this civ
        playerName = m_pCurrentPolicies->GetPlayer()->getCivilizationShortDescription();

        FILogFile* pLog;
        pLog = LOGFILEMGR.GetLog(GetLogFileName(playerName), FILogFile::kDontTimeStamp);

        // Get the leading info for this line
        strBaseString.Format("%03d, ", GC.getGame().getElapsedGameTurns());
        strBaseString += playerName + ", ";

        strTemp.Format("%s, Freedom: %d, Order: %d, Autocracy: %d", decisionState.c_str(), iWeightFreedom, iWeightOrder, iWeightAutocracy);

        strOutBuf = strBaseString + strTemp;
        pLog->Msg(strOutBuf);
    }
}
Example #4
0
//------------------------------------------------------------------------------
//string GetGreatPersonRateModifierDetails(UnitClassTypes eGreatPersonClass);
int CvLuaLeague::lGetGreatPersonRateModifierDetails(lua_State* L)
{
	CvLeague* pLeague = GetInstance(L);
	const UnitClassTypes eGreatPersonClass = (UnitClassTypes) lua_tointeger(L, 2);

	CvString sValue = pLeague->GetGreatPersonRateModifierDetails(eGreatPersonClass);
	lua_pushstring(L, sValue.c_str());
	return 1;
}
Example #5
0
//------------------------------------------------------------------------------
//string GetLeagueSplashNextEraDetails(LeagueSpecialSessionTypes eGoverningSpecialSession, bool bJustFounded);
int CvLuaLeague::lGetLeagueSplashNextEraDetails(lua_State* L)
{
	CvLeague* pLeague = GetInstance(L);
	const LeagueSpecialSessionTypes eGoverningSpecialSession = (LeagueSpecialSessionTypes) lua_tointeger(L, 2);
	const bool bJustFounded = lua_toboolean(L, 3);

	CvString sValue = pLeague->GetLeagueSplashNextEraDetails(eGoverningSpecialSession, bJustFounded);
	lua_pushstring(L, sValue.c_str());
	return 1;
}
Example #6
0
//------------------------------------------------------------------------------
//string GetProjectDetails(LeagueProjectTypes eProject, PlayerTypes eObserver);
int CvLuaLeague::lGetProjectDetails(lua_State* L)
{
	CvLeague* pLeague = GetInstance(L);
	const LeagueProjectTypes eProject = (LeagueProjectTypes) lua_tointeger(L, 2);
	const PlayerTypes eObserver = (PlayerTypes) luaL_optint(L, 3, NO_PLAYER);

	CvString sValue = pLeague->GetProjectDetails(eProject, eObserver);
	lua_pushstring(L, sValue.c_str());
	return 1;
}
Example #7
0
//------------------------------------------------------------------------------
//string GetMemberDetails(PlayerTypes eMember, PlayerTypes eObserver);
int CvLuaLeague::lGetMemberDetails(lua_State* L)
{
	CvLeague* pLeague = GetInstance(L);
	const PlayerTypes eMember = (PlayerTypes) lua_tointeger(L, 2);
	const PlayerTypes eObserver = (PlayerTypes) lua_tointeger(L, 3);

	CvString sValue = pLeague->GetMemberDetails(eMember, eObserver);
	lua_pushstring(L, sValue.c_str());
	return 1;
}
Example #8
0
//------------------------------------------------------------------------------
//string GetResolutionName(ResolutionTypes eResolution, int iResolutionID, int iProposerChoice, bool bIncludePrefix);
int CvLuaLeague::lGetResolutionName(lua_State* L)
{
	CvLeague* pLeague = GetInstance(L);
	const ResolutionTypes eResolution = (ResolutionTypes) lua_tointeger(L, 2);
	const int iResolutionID = lua_tointeger(L, 3);
	const int iProposerChoice = lua_tointeger(L, 4);
	const bool bIncludePrefix = lua_toboolean(L, 5);

	CvString sValue = pLeague->GetResolutionName(eResolution, iResolutionID, iProposerChoice, bIncludePrefix);
	lua_pushstring(L, sValue.c_str());
	return 1;
}
Example #9
0
//------------------------------------------------------------------------------
//string GetResolutionDetails(ResolutionTypes eResolution, PlayerTypes eObserver, int iResolutionID, int iProposerChoice);
int CvLuaLeague::lGetResolutionDetails(lua_State* L)
{
	CvLeague* pLeague = GetInstance(L);
	const ResolutionTypes eResolution = (ResolutionTypes) lua_tointeger(L, 2);
	const PlayerTypes eObserver = (PlayerTypes) lua_tointeger(L, 3);
	const int iResolutionID = lua_tointeger(L, 4);
	const int iProposerChoice = lua_tointeger(L, 5);

	CvString sValue = pLeague->GetResolutionDetails(eResolution, eObserver, iResolutionID, iProposerChoice);
	lua_pushstring(L, sValue.c_str());
	return 1;
}
void CvTacticalAnalysisMap::Dump()
{
	if (m_ePlayer==NO_PLAYER)
		return;

	bool bLogging = GC.getLogging() && GC.getAILogging() && (GET_PLAYER(m_ePlayer).isMajorCiv() || GET_PLAYER(m_ePlayer).isBarbarian()) && GET_PLAYER(m_ePlayer).IsAtWar();
	if (bLogging)
	{
		CvString fname = CvString::format( "TacticalCells_%s_%03d.txt", GET_PLAYER(m_ePlayer).getCivilizationAdjective(), GC.getGame().getGameTurn() );
		FILogFile* pLog=LOGFILEMGR.GetLog( fname.c_str(), FILogFile::kDontTimeStamp );
		if (pLog)
		{
			pLog->Msg( "#x,y,visible,terrain,owner,enemy,targettype,underattack,zoneid,dominance,zonetype,fstrength,estrength,city\n" );
			for (int i=0; i<GC.getMap().numPlots(); i++)
			{
				CvTacticalAnalysisCell* pCell = GetCell(i);

				if (!pCell->IsRevealed())
					continue;

				CvTacticalDominanceZone* pZone = GetZoneByID( pCell->GetDominanceZone() );

				int iZoneFriendlyStrength = pZone ? pZone->GetFriendlyRangedStrength() + pZone->GetOverallFriendlyStrength() : -1;
				int iZoneEnemyStrength = pZone ? pZone->GetEnemyRangedStrength() + pZone->GetOverallEnemyStrength() : -1;
				CvCity* pCity = pZone ? pZone->GetZoneCity() : NULL;

				CvString dump = CvString::format( "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%s\n", 
					GC.getMap().plotByIndex(i)->getX(), GC.getMap().plotByIndex(i)->getY(),
					pCell->IsVisible(), (int)GC.getMap().plotByIndex(i)->getTerrainType(), (int)GC.getMap().plotByIndex(i)->getOwner(), 
					(int)pCell->IsEnemyTerritory(), (int)pCell->GetTargetType(), (int)pCell->IsSubjectToAttack(), 
					pZone ? pZone->GetDominanceZoneID() : -1, pZone ? pZone->GetOverallDominanceFlag() : -1, pZone ? pZone->GetTerritoryType() : -1, 
					iZoneFriendlyStrength, iZoneEnemyStrength, pCity ? pCity->getName().c_str() : "no city" );
				pLog->Msg( dump.c_str() );
			}
			pLog->Close();
		}
	}
}
//------------------------------------------------------------------------------
bool CvDllGameContext::GetDefineSTRING(char* szBuffer, size_t lenBuffer, const char* szName, bool bReportErrors)
{
	if(szBuffer != NULL && lenBuffer > 0)
	{
		CvString strDefine = GC.getDefineSTRING(szName, bReportErrors);
		if(strDefine.size() < lenBuffer)
		{
			strncpy_s(szBuffer, lenBuffer, strDefine.c_str(), strDefine.size());
			return true;
		}
	}

	return false;
}
Example #12
0
bool CvXMLLoadUtilityModTools::isModularArt(const char* szLocationName)
{
/************************************************************************************************/
/* DEBUG_IS_MODULAR_ART                    05/12/08                                Faichele     */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
#if (DEBUG_IS_MODULAR_ART == 1)
	CvString szDebugBuffer;
	szDebugBuffer.Format("=== isModularArt BEGIN ===");
	gDLL->logMsg("CvXMLLoadUtilityModTools_isModularArt.log", szDebugBuffer.c_str());

	szDebugBuffer.Format(" Location name: '%s'", szLocationName);
	gDLL->logMsg("CvXMLLoadUtilityModTools_isModularArt.log", szDebugBuffer.c_str());
#endif

	//the passed is crap, we don't want to continue anything with it
	if (szLocationName == NULL || szLocationName == "" || szLocationName == "None" || szLocationName == "NONE" )
	{
#if (DEBUG_IS_MODULAR_ART == 1)
		szDebugBuffer.Format(" EMPTY location, aborting.");
		gDLL->logMsg("CvXMLLoadUtilityModTools_isModularArt.log", szDebugBuffer.c_str());
#endif	
		return false;
	}

	// Dir where the Civ4BeyondSword.exe is started from
/************************************************************************************************/
/* Afforess	                  Start		 06/15/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	CvString m_szFolderPath = GC.getInitCore().getDLLPath() + "\\";
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/


	#if (DEBUG_IS_MODULAR_ART == 1)
		szDebugBuffer.Format(" Complete path (with Assets dir): %s", m_szFolderPath.c_str());
		gDLL->logMsg("CvXMLLoadUtilityModTools_isModularArt.log", szDebugBuffer.c_str());
	#endif

	m_szFolderPath += szLocationName;		// where the tag points to, usually "Art\filename.xxx"

#if (DEBUG_IS_MODULAR_ART == 1)
	szDebugBuffer.Format("  Path WITH given location: '%s'", m_szFolderPath.c_str());
	gDLL->logMsg("CvXMLLoadUtilityModTools_isModularArt.log", szDebugBuffer.c_str());
#endif
	int iReplaced = 0;
	
	iReplaced = m_szFolderPath.Replace('/','\\');
#if (DEBUG_IS_MODULAR_ART == 1)
	
	szDebugBuffer.Format("  Replaced %i occurrences of '/' with '\\'.", iReplaced);
	gDLL->logMsg("CvXMLLoadUtilityModTools_isModularArt.log", szDebugBuffer.c_str());

#endif

	iReplaced = m_szFolderPath.Replace(CvString("\\\\"),CvString("\\"));
#if (DEBUG_IS_MODULAR_ART == 1)
	szDebugBuffer.Format("  Replaced %i occurrences of '\\\\' with '\\'.", iReplaced);
	gDLL->logMsg("CvXMLLoadUtilityModTools_isModularArt.log", szDebugBuffer.c_str());	

	szDebugBuffer.Format("  Path WITH given location: '%s'", m_szFolderPath.c_str());
	gDLL->logMsg("CvXMLLoadUtilityModTools_isModularArt.log", szDebugBuffer.c_str());
#endif
	FILE *file;
	DWORD dwAttr = GetFileAttributes(m_szFolderPath.c_str());
	if(dwAttr != 0xffffffff && (dwAttr & FILE_ATTRIBUTE_DIRECTORY)) 
	{
#if (DEBUG_IS_MODULAR_ART == 1)
		szDebugBuffer.Format(" '%s' is a DIRECTORY, no modular art?", m_szFolderPath.c_str());
		gDLL->logMsg("CvXMLLoadUtilityModTools_isModularArt.log", szDebugBuffer.c_str());
#endif
		return false;
	}
	else
	{
		file = fopen(m_szFolderPath.c_str(), "rb");
	}

/************************************************************************************************/
/* DEBUG_IS_MODULAR_ART                    END                                                  */
/************************************************************************************************/

	if (file == NULL) 
	{
		return false;		
	}
	fclose(file);

#if (DEBUG_IS_MODULAR_ART == 1)
	szDebugBuffer.Format("=== isModularArt END ===");
	gDLL->logMsg("CvXMLLoadUtilityModTools_isModularArt.log", szDebugBuffer.c_str());
#endif	

	return true;
}
Example #13
0
bool CvXMLLoadUtilityModTools::isCommaFile(CvString *pszTextVal, const char* szDirName)
{
#if (DEBUG_IS_MODULAR_ART == 1)
	CvString szDebugBuffer;
	szDebugBuffer.Format("=== isCommaFile BEGIN ===");
	gDLL->logMsg("CvXMLLoadUtilityModTools_isCommaFile.log", szDebugBuffer.c_str());

	szDebugBuffer.Format(" Text value: %s,  Directory name: '%s'", pszTextVal->c_str(), szDirName);
	gDLL->logMsg("CvXMLLoadUtilityModTools_isCommaFile.log", szDebugBuffer.c_str());
#endif

	string::size_type posComma = (*pszTextVal).find_first_of(',');

	if(posComma != string::npos) //if no comma found at all, return false
	{

#if (DEBUG_IS_MODULAR_ART == 1)
		szDebugBuffer.Format(" Found a ',' at position %i (total length %i)", (int)posComma, (*pszTextVal).GetLength());
		gDLL->logMsg("CvXMLLoadUtilityModTools_isCommaFile.log", szDebugBuffer.c_str());
#endif
		CvString szTempLocation;
		CvString szAppend = " ";
		int iCountComma = 0;
		CvString szLocationNameStripComma;
		// Check how many comma's we have in the string and how many Button Files		

#if (DEBUG_IS_MODULAR_ART == 1)
		std::vector<CvString> asTagParts;
		pszTextVal->getTokens(CvString(","), asTagParts);
		iCountComma = asTagParts.size();

		szDebugBuffer.Format(" Total number of ',' in pszTextVal: %i", iCountComma);
		gDLL->logMsg("CvXMLLoadUtilityModTools_isCommaFile.log", szDebugBuffer.c_str());
		for (std::vector<CvString>::iterator it = asTagParts.begin(); it != asTagParts.end(); it++)
		{
			szDebugBuffer.Format("  - Token %s", (*it).c_str());
			gDLL->logMsg("CvXMLLoadUtilityModTools_isCommaFile.log", szDebugBuffer.c_str());
		}
#else
		szLocationNameStripComma = *pszTextVal;
		for ( int i = 0; i < szLocationNameStripComma.GetLength(); i++)
		{
			if (szLocationNameStripComma[i] == 44) // "," = 44 (ASCII)
			{
			  iCountComma++;
			}
		}		
#endif

		

#if (DEBUG_IS_MODULAR_ART == 1)
		CvString szButtonsString;
		for (std::vector<CvString>::iterator it = asTagParts.begin(); it != asTagParts.end(); it++)
		{
			bool bDigitsOnly = true;
			for (int i = 0; i < (*it).GetLength(); i++)
			{
				if (!isdigit((*it)[i]))
					bDigitsOnly = false;
			}
			if (!bDigitsOnly)
				szButtonsString += ((*it) + ",");
		}
		// Eliminate comma at end of string, if there is one
		if (szButtonsString.GetLength() > 0 && szButtonsString[szButtonsString.GetLength()] == ',')
			szButtonsString = szButtonsString.substr(0, szButtonsString.GetLength() - 1);

		szDebugBuffer.Format(" Button art string after eliminating numerical indices: %s", szButtonsString.c_str());
		gDLL->logMsg("CvXMLLoadUtilityModTools_isCommaFile.log", szDebugBuffer.c_str());

#else
		// determine the append string at the end of the tag
		bool bContinue = true;
		szTempLocation = *pszTextVal;
		while ( bContinue)
		{
			posComma = szTempLocation.find_first_of(',');
			if(posComma != string::npos) //Prevent Null pointer deletion
			{
				szTempLocation = szTempLocation.substr(szTempLocation.find(",")+1);
				if (isdigit(szTempLocation[0]))  //We found the Append
				{					
					bContinue = false;
				}
			}
			else break;			
		}
		if (!bContinue )
		{
			szAppend = "," + szTempLocation;
		}
#endif

std::vector<CvString> vecButtonArtFile;
#if (DEBUG_IS_MODULAR_ART == 1)
	szButtonsString.getTokens(CvString(","), vecButtonArtFile);
	szDebugBuffer.Format(" Button art vector size after tokenizing by ',': %i", vecButtonArtFile.size());
	gDLL->logMsg("CvXMLLoadUtilityModTools_isCommaFile.log", szDebugBuffer.c_str());
#else
		// set Button Array
		// Array to hold the Button art files
		CvString szTempLocationSubstr;
		szTempLocation = *pszTextVal;
		while (true)
		{
			posComma = szTempLocation.find_first_of(',');
			if(posComma != string::npos) //Prevent Null pointer deletion
			{
				if (szTempLocation[0] == 44) // "," = 44 (ASCII)
				{
					szTempLocation = szTempLocation.substr(szTempLocation.find(",")+1);
				}
				szTempLocationSubstr = szTempLocation;
				posComma = szTempLocationSubstr.find_first_of(',');
				if(posComma != string::npos) //Prevent Null pointer deletion
				{
					szTempLocationSubstr.erase(posComma);
					if (!isdigit(szTempLocationSubstr[0]))
					{
						vecButtonArtFile.push_back(szTempLocationSubstr);
					}
					else break;
				}
				szTempLocation = szTempLocation.substr(szTempLocation.find(",")+1);
			}
			else if (szTempLocation.GetLength() >= 1)
			{
				if (!isdigit(szTempLocationSubstr[0]))
				{
					vecButtonArtFile.push_back(szTempLocationSubstr);
				}
				break;
			}
			else break;
		}		
#endif

		//Check if we need to modularize the files
		bool bNeedChange = false;
/************************************************************************************************/
/* Afforess	                  Start		 06/15/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
		CvString m_szFolderPath = GC.getInitCore().getDLLPath() + "//";
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

		m_szFolderPath += szDirName;			// "Modules\Modules\ModuleXXX" 
		for ( unsigned int i = 0; i < vecButtonArtFile.size(); i++)
		{
			szTempLocation = m_szFolderPath;
			szTempLocation += vecButtonArtFile[i];
			//set the Slash properly
			for ( int j = 0; j < szTempLocation.GetLength(); j++)
			{
				if ( szTempLocation[j] == 47)  // 47 = "/"
				{
					szTempLocation[j] = 92;  //92 = "\\", actually 1 backslash of course
				}
			}

			FILE *file = fopen(szTempLocation , "rb");
			if (file != NULL)
			{
				vecButtonArtFile[i] = szDirName + vecButtonArtFile[i];
				fclose(file);
				bNeedChange = true;
			}
		}

		// Now set the new tag string properly
		if (bNeedChange)
		{
			if (szLocationNameStripComma[0] == 44)
			{
				szTempLocation = ",";
			}
			else
			{
				szTempLocation = 0;
			}
			for ( unsigned int i = 0; i < vecButtonArtFile.size(); i++)
			{
				if (i != 0) szTempLocation += ",";
				szTempLocation += vecButtonArtFile[i];
			}
			if (szAppend[0] == 44)   // "," = 44 (ASCII)
			{
				szTempLocation += szAppend;
			}
			*pszTextVal = szTempLocation;
			return true;
		}	
	} 
	return false;
}
Example #14
0
// WARNING WARNING WARNING WARNING
// the p_szLogWrite->XmlArtTagVerification can cause CTD because of memory overflow
// If too much is parsed into the XmlArtTagVerification method!!
void CvXMLLoadUtilityModTools::setLocationName( CvString *pszTextVal, const char* szDirName)
{
#if (DEBUG_IS_MODULAR_ART == 1)
	CvString szDebugBuffer;
	szDebugBuffer.Format("=== setLocationName BEGIN ===");
	gDLL->logMsg("CvXMLLoadUtilityModTools_setLocationName.log", szDebugBuffer.c_str());

	szDebugBuffer.Format(" Text value: '%s', Directory name: '%s'", pszTextVal->c_str(), szDirName);
	gDLL->logMsg("CvXMLLoadUtilityModTools_setLocationName.log", szDebugBuffer.c_str());
#endif

	std::string szFiraxisLoad = "NONE";
	if (szDirName == szFiraxisLoad) //non modular loading doesn't need this method
	{
//#if (DEBUG_IS_MODULAR_ART == 1)
//	szDebugBuffer.Format("DirName == NONE, exiting?");
//	gDLL->logMsg("CvXMLLoadUtilityModTools_setLocationName.log", szDebugBuffer.c_str());
//
//	szDebugBuffer.Format("=== setLocationName END ===");
//	gDLL->logMsg("CvXMLLoadUtilityModTools_setLocationName.log", szDebugBuffer.c_str());
//#endif

		return;
	}
	CvString szModular = szDirName;
	CvString szTextVal = *pszTextVal;
	szModular = szModular + szTextVal;

	CvXMLLoadUtility* p_szLogWrite = new CvXMLLoadUtility;

	if (isExcludedFile(szTextVal)) // These are special files that are relative to the Directory of Civ4BeyondSword.exe
	{
		if ( isModularArt(szModular))
		{			
			szTextVal = gDLL->getModName();
			szTextVal += "Assets\\";
			szTextVal += szModular;
			writeThm(szTextVal);
		}
		else
		{
#ifdef _DEBUG
		//the passed is crap, we don't want to continue anything with it
/*
		if ( szTextVal == "" )	// this shouldn't exist
		{
			p_szLogWrite->XmlArtTagVerification("CRASH WARNING, Your theme <Path> tag is found emtpy in: %s\\%s", szDirName.GetCString(), GC.getCurrentXMLFile().GetCString());
		}
		else if (szTextVal == "None")	// this shouldn't exist!
		{
			p_szLogWrite->XmlArtTagVerification("CRASH WARNING, Your theme <Path> tag is set to: %s in: %s\\%s", szTextVal.GetCString(), szDirName.GetCString(), GC.getCurrentXMLFile().GetCString());		
		}
		else
		{
		}
*/
			p_szLogWrite->XmlArtTagVerification("CRASH WARNING, Your theme <Path> %s, seems not to be relative to the Module path: %s", szTextVal.GetCString(), szDirName);		
#endif
		}
	}
	else if (isCommaFile(&szTextVal, szDirName)) // These are tags with a comma, mostly having 2button types even
	{
#ifdef _DEBUG
		//the passed is crap, we don't want to continue anything with it
		if ( szTextVal == "" )
		{
			p_szLogWrite->XmlArtTagVerification("One art tag is found emtpy in: %s", GC.getCurrentXMLFile().GetCString());
		}
		else if (szTextVal == "None")
		{
			p_szLogWrite->XmlArtTagVerification("One art tag is set to: %s in: %s", szTextVal.GetCString(), GC.getCurrentXMLFile().GetCString());		
		}
		else
		{		
			p_szLogWrite->XmlArtTagVerification("One art tag: %s, seems not to be relative to the module path in: %s", szTextVal.GetCString(), GC.getCurrentXMLFile().GetCString());		
		}
#endif
	}	
	else
	{
		if ( isModularArt(szModular))
		{
			szTextVal = szModular;
		}
		else
		{
#ifdef _DEBUG
		//the passed is crap, we don't want to continue anything with it
		if ( szTextVal == "" )
		{
			p_szLogWrite->XmlArtTagVerification("One art tag is found emtpy in: %s", GC.getCurrentXMLFile().GetCString());
		}
		else if (szTextVal == "None")
		{
			p_szLogWrite->XmlArtTagVerification("One art tag is set to: %s in: %s", szTextVal.GetCString(), GC.getCurrentXMLFile().GetCString());		
		}
		else
		{		
			p_szLogWrite->XmlArtTagVerification("One art tag: %s, seems not to be relative to the module path in: %s", szTextVal.GetCString(), GC.getCurrentXMLFile().GetCString());		
		}
#endif
		}
	}
	*pszTextVal = szTextVal;

#if (DEBUG_IS_MODULAR_ART == 1)
	szDebugBuffer.Format(" Assigned OUT text value: '%s'", pszTextVal->c_str());
	gDLL->logMsg("CvXMLLoadUtilityModTools_setLocationName.log", szDebugBuffer.c_str());

	szDebugBuffer.Format("=== setLocationName END ===");
	gDLL->logMsg("CvXMLLoadUtilityModTools_setLocationName.log", szDebugBuffer.c_str());
#endif

	SAFE_DELETE(p_szLogWrite);
}
	kStream << kPopupInfo.eButtonPopupType;

	CvString strDummy = kPopupInfo.szText;
	kStream << strDummy;

	return kStream;
}
//------------------------------------------------------------------------------
FDataStream & operator>>(FDataStream& kStream, CvPopupInfo& kPopupInfo)
{
	// Version number to maintain backwards compatibility
	uint uiVersion;
	kStream >> uiVersion;

	kStream >> kPopupInfo.iData1;
	kStream >> kPopupInfo.iData2;
	kStream >> kPopupInfo.iData3;
	kStream >> kPopupInfo.iFlags;
	kStream >> kPopupInfo.bOption1;
	kStream >> kPopupInfo.bOption2;

	kStream >> kPopupInfo.eButtonPopupType;

	CvString strDummy;
	kStream >> strDummy;

	strcpy_s(kPopupInfo.szText, strDummy.c_str());

	return kStream;
}
/// Get center of mass of units in army (account for world wrap!)
CvPlot* CvArmyAI::GetCenterOfMass(float* pfVarX, float* pfVarY)
{
	int iTotalX = 0;
	int iTotalY = 0;
	int iNumUnits = 0;

	UnitHandle pUnit = GetFirstUnit();
	if (!pUnit)
		return NULL;

	int iTotalX2 = 0;
	int iTotalY2 = 0;
	int iWorldWidth = GC.getMap().getGridWidth();
	int iWorldHeight = GC.getMap().getGridHeight();

	//the first unit is our reference ...
	int iRefX = pUnit->getX();
	int iRefY = pUnit->getY();
	iNumUnits++;
	pUnit = GetNextUnit();

	while(pUnit)
	{
		int iDX = pUnit->getX() - iRefX;
		int iDY = pUnit->getY() - iRefY;

		if (GC.getMap().isWrapX())
		{
			if( iDX > +(iWorldWidth / 2))
				iDX -= iWorldWidth;
			if( iDX < -(iWorldWidth / 2))
				iDX += iWorldWidth;
		}
		if (GC.getMap().isWrapY())
		{
			if( iDY > +(iWorldHeight / 2))
				iDY -= iWorldHeight;
			if( iDY < -(iWorldHeight / 2))
				iDY += iWorldHeight;
		}

		iTotalX += iDX;
		iTotalY += iDY;
		iTotalX2 += iDX*iDX;
		iTotalY2 += iDY*iDY;
		iNumUnits++;

		pUnit = GetNextUnit();
	}

	if (iNumUnits==0)
		return NULL;

	//this is for debugging
	float fVarX = (iTotalX2 / (float)iNumUnits) - (iTotalX/(float)iNumUnits)*(iTotalX/(float)iNumUnits);
	float fVarY = (iTotalY2 / (float)iNumUnits) - (iTotalY/(float)iNumUnits)*(iTotalY/(float)iNumUnits);

	//finally, compute average (with rounding)
	int iAvgX = (iTotalX + (iNumUnits / 2)) / iNumUnits + iRefX;
	int iAvgY = (iTotalY + (iNumUnits / 2)) / iNumUnits + iRefY;

	if (fVarX > 64 || fVarY > 64)
	{
		CvString msg = CvString::format("Warning: Army %d with %d units Center of Mass (%d,%d) has a large variance (%.2f,%.2f)\n", GetID(), iNumUnits, iAvgX, iAvgY, fVarX, fVarY);
		OutputDebugString( msg.c_str() );
	}

	//this handles wrapped coordinates
	CvPlot* pCOM = GC.getMap().plot(iAvgX, iAvgY);

	if (!pCOM)
		return NULL;

	if (pfVarX)
		*pfVarX = fVarX;
	if (pfVarY)
		*pfVarY = fVarY;

	//don't return it directly but use the plot of the closest unit
	pUnit = GetFirstUnit();
	std::vector<SPlotWithScore> vPlots;
	while (pUnit)
	{
		if (pUnit->plot()->getDomain()==GetDomainType())
		{
			int iDistToCOM = plotDistance(*pUnit->plot(),*pCOM);
			int iDistToTarget = plotDistance(pUnit->getX(),pUnit->getY(),GetGoalX(),GetGoalY());
			vPlots.push_back( SPlotWithScore(pUnit->plot(),iDistToCOM*100+iDistToTarget) );
		}

		pUnit = GetNextUnit();
	}

	if (vPlots.empty())
		return NULL;

	//this sorts ascending!
	std::sort(vPlots.begin(),vPlots.end());
	return vPlots.front().pPlot;
}
/// Get center of mass of units in army (account for world wrap!)
CvPlot* CvArmyAI::GetCenterOfMass(DomainTypes eDomainRequired)
{
	int iTotalX = 0;
	int iTotalY = 0;
	int iNumUnits = 0;

#if defined(MOD_BALANCE_CORE)
	UnitHandle pUnit = GetFirstUnit();

	if (!pUnit)
		return NULL;

	int iTotalX2 = 0;
	int iTotalY2 = 0;
	int iWorldWidth = GC.getMap().getGridWidth();
	int iWorldHeight = GC.getMap().getGridHeight();

	//the first unit is our reference ...
	int iRefX = pUnit->getX();
	int iRefY = pUnit->getY();
	iNumUnits++;
	pUnit = GetNextUnit();

	while(pUnit)
	{
		int iDX = pUnit->getX() - iRefX;
		int iDY = pUnit->getY() - iRefY;

		if (GC.getMap().isWrapX())
		{
			if( iDX > +(iWorldWidth / 2))
				iDX -= iWorldWidth;
			if( iDX < -(iWorldWidth / 2))
				iDX += iWorldWidth;
		}
		if (GC.getMap().isWrapY())
		{
			if( iDY > +(iWorldHeight / 2))
				iDY -= iWorldHeight;
			if( iDY < -(iWorldHeight / 2))
				iDY += iWorldHeight;
		}

		iTotalX += iDX;
		iTotalY += iDY;
		iTotalX2 += iDX*iDX;
		iTotalY2 += iDY*iDY;
		iNumUnits++;

		pUnit = GetNextUnit();
	}

	if (iNumUnits==0)
		return NULL;

	//this is for debugging
	float fVarX = (iTotalX2 / (float)iNumUnits) - (iTotalX/(float)iNumUnits)*(iTotalX/(float)iNumUnits);
	float fVarY = (iTotalY2 / (float)iNumUnits) - (iTotalY/(float)iNumUnits)*(iTotalY/(float)iNumUnits);

	//finally, compute average (with rounding)
	int iAvgX = (iTotalX + (iNumUnits / 2)) / iNumUnits + iRefX;
	int iAvgY = (iTotalY + (iNumUnits / 2)) / iNumUnits + iRefY;

	if (fVarX > 64 || fVarY > 64)
	{
		CvString msg = CvString::format("Warning: Army %d with %d units Center of Mass (%d,%d) has a large variance (%.2f,%.2f)\n", GetID(), iNumUnits, iAvgX, iAvgY, fVarX, fVarY);
		OutputDebugString( msg.c_str() );
	}

	//this handles wrapped coordinates
	CvPlot* pCOM = GC.getMap().plot(iAvgX, iAvgY);

	if (!pCOM)
		return NULL;

	//don't return it directly but use the plot of the closest unit
	pUnit = GetFirstUnit();
	std::vector<SPlotWithScore> vPlots;
	while (pUnit)
	{
		if (eDomainRequired == NO_DOMAIN || pUnit->plot()->getDomain()==eDomainRequired)
			vPlots.push_back( SPlotWithScore(pUnit->plot(),plotDistance(*pUnit->plot(),*pCOM)) );

		pUnit = GetNextUnit();
	}

	if (vPlots.empty())
		return NULL;

	//this sorts ascending!
	std::sort(vPlots.begin(),vPlots.end());
	return vPlots.front().pPlot;

#else
	CvPlot* pRtnValue = NULL;
	UnitHandle pUnit;
	int iReferenceUnitX = -1;
	int iWorldWidth = GC.getMap().getGridWidth();

	pUnit = GetFirstUnit();
	if(pUnit)
	{
		iReferenceUnitX = pUnit->getX();
	}

	while(pUnit)
	{
		int iUnitX = pUnit->getX();

		bool bWorldWrapAdjust = false;
		int iDiff = iUnitX - iReferenceUnitX;
		if(abs(iDiff) > (iWorldWidth / 2))
		{
			bWorldWrapAdjust = true;
		}

		if(bWorldWrapAdjust)
		{
			iTotalX += iUnitX + iWorldWidth;
		}
		else
		{
			iTotalX += iUnitX;
		}
		iTotalY += pUnit->getY();
		iNumUnits++;
		pUnit = GetNextUnit();
	}

	if(iNumUnits > 0)
	{
		int iAverageX = (iTotalX + (iNumUnits / 2)) / iNumUnits;
		if(iAverageX >= iWorldWidth)
		{
			iAverageX = iAverageX - iWorldWidth;
		}
		int iAverageY = (iTotalY + (iNumUnits / 2)) / iNumUnits;
		pRtnValue = GC.getMap().plot(iAverageX, iAverageY);
	}

	// Domain check
	if (eDomainRequired != NO_DOMAIN && pRtnValue)
	{
		if (pRtnValue->isWater() && eDomainRequired == DOMAIN_LAND || !pRtnValue->isWater() && eDomainRequired == DOMAIN_SEA)
		{
			// Find an adjacent plot that works
			for (int iI = 0; iI < NUM_DIRECTION_TYPES; iI++)
			{
				CvPlot *pLoopPlot = plotDirection(pRtnValue->getX(), pRtnValue->getY(), ((DirectionTypes)iI));
				if (pLoopPlot != NULL)
				{
					if (pLoopPlot->isWater() && eDomainRequired == DOMAIN_SEA || !pLoopPlot->isWater() && eDomainRequired == DOMAIN_LAND)
					{
						return pLoopPlot;
					}
				}
			}

			// Try two plots out if really having problems
			for (int iDX = -2; iDX <= 2; iDX++)
			{
				for (int iDY = -2; iDY <= 2; iDY++)
				{
					CvPlot *pLoopPlot = plotXYWithRangeCheck(pRtnValue->getX(), pRtnValue->getY(), iDX, iDY, 2);
					if (pLoopPlot)
					{
						if (plotDistance(pRtnValue->getX(), pRtnValue->getY(), pLoopPlot->getX(), pLoopPlot->getY()) == 2)
						{
							if (pLoopPlot->isWater() && eDomainRequired == DOMAIN_SEA || !pLoopPlot->isWater() && eDomainRequired == DOMAIN_LAND)
							{
								return pLoopPlot;
							}
						}
					}
				}
			}

			// Give up - just use location of first unit
			pUnit = GetFirstUnit();
			pRtnValue = pUnit->plot();
		}
	}
	return pRtnValue;
#endif
}