Exemple #1
0
// String version
bool	getVarFromConfigFile(CConfigFile &cf, const string &name, string &variable, const string &defaultValue = string(""))
{
	CConfigFile::CVar	*ptr = cf.getVarPtr(name);
	bool	success;
	variable = ((success = (ptr != NULL)) ? ptr->asString() : defaultValue);
	return success;
}
Exemple #2
0
// Float version
bool	getVarFromConfigFile(CConfigFile &cf, const string &name, float &variable, float defaultValue = 0.0f)
{
	CConfigFile::CVar	*ptr = cf.getVarPtr(name);
	bool	success;
	variable = ((success = (ptr != NULL)) ? ptr->asFloat() : defaultValue);
	return success;
}
Exemple #3
0
// Bool version
bool	getVarFromConfigFile(CConfigFile &cf, const string &name, bool &variable, bool defaultValue = false)
{
	CConfigFile::CVar	*ptr = cf.getVarPtr(name);
	bool	success;
	variable = ((success = (ptr != NULL)) ? (ptr->asInt() != 0) : defaultValue);
	return success;
}
Exemple #4
0
double CConfiguration::getValue(const string &varName, double defaultValue)
{
	if (m_ConfigFile.exists(varName)) return m_ConfigFile.getVar(varName).asDouble();
	CConfigFile::CVar varToCopy;
	varToCopy.forceAsDouble(defaultValue);	
	m_ConfigFile.insertVar(varName, varToCopy);
	return defaultValue;
}
Exemple #5
0
bool CConfiguration::getValue(const string &varName, bool defaultValue)
{
	if (m_ConfigFile.exists(varName)) return m_ConfigFile.getVar(varName).asBool();
	CConfigFile::CVar varToCopy;
	varToCopy.forceAsInt(defaultValue ? 1 : 0);	
	m_ConfigFile.insertVar(varName, varToCopy);
	return defaultValue;
}
Exemple #6
0
float CConfiguration::getValue(const string &varName, float defaultValue)
{
	if (ConfigFile.exists(varName)) return ConfigFile.getVar(varName).asFloat();
	CConfigFile::CVar varToCopy;
	varToCopy.forceAsDouble((double)defaultValue);	
	ConfigFile.insertVar(varName, varToCopy);
	return defaultValue;
}
Exemple #7
0
string CConfiguration::getValue(const string &varName, const string &defaultValue)
{
	if (ConfigFile.exists(varName)) return ConfigFile.getVar(varName).asString();
	CConfigFile::CVar varToCopy;
	varToCopy.forceAsString(defaultValue);
	ConfigFile.insertVar(varName, varToCopy);
	return defaultValue;
}
Exemple #8
0
ucstring CConfiguration::getValue(const string &varName, const ucstring &defaultValue)
{
	if (m_ConfigFile.exists(varName)) return ucstring::makeFromUtf8(m_ConfigFile.getVar(varName).asString());
	CConfigFile::CVar varToCopy;
	varToCopy.forceAsString(defaultValue.toUtf8());
	m_ConfigFile.insertVar(varName, varToCopy);
	return defaultValue;
}
Exemple #9
0
void CConfiguration::configRemapExtensions()
{
	CConfigFile::CVar *var;
	var = ConfigFile.getVarPtr("RemapExtensions");
	uint varsize = var->size();
	for (uint i = 0; i < varsize; i += 2)
	CPath::remapExtension(var->asString(i), var->asString(i + 1), true);
}
Exemple #10
0
int CConfiguration::getValue(const string &varName, int defaultValue)
{
	if (ConfigFile->exists(varName)) return ConfigFile->getVar(varName).asInt();
	CConfigFile::CVar varToCopy;
	varToCopy.forceAsInt(defaultValue);	
	ConfigFile->insertVar(varName, varToCopy);
	return defaultValue;
}
Exemple #11
0
void CIconWnd::updateIcon()
{
    // Get IconPath
    if (IconPath == "")
    {
        CConfigFile::CVar *var = theApp.ConfigFile.getVarPtr("IconPath");
        if (var)
        {
            IconPath = var->asString();
            for (uint i=0 ; i<var->size() ; i++)
                CPath::addSearchPath(var->asString(i), true, false, NULL);
        }
        else
        {
            nlinfo("!! IconPath missing in .cfg, Please complete the config file !!");
            IconPath = "\\\\amiga\\3d\\Database\\Interfaces\\";
            nlinfo("default to : IconPath = \"\\\\amiga\\3d\\Database\\Interfaces\\\"");
            CPath::addSearchPath(IconPath, true, false, NULL);
        }
    }

    NLMISC::CBitmap icon;
    NLMISC::CRGBA color;

    bitmap.reset();
    bitmap.convertToType(NLMISC::CBitmap::RGBA);
    bitmap.resample(40, 40);

    // back icon
    if (loadIcon(strIconBack, icon))
    {
        // back icon color
        if (getColorFromStr(strIconBackColor, color))
            modulateIcon(icon, color);

        bitmap = icon;

        // base icon
        addIconLayer(bitmap, strIcon, strIconColor);
    }
    else
    {
        // base icon
        loadIcon(strIcon, icon);

        // base icon color
        if (getColorFromStr(strIconColor, color))
            modulateIcon(icon, color);

        bitmap = icon;
    }

    // overlay icon
    addIconLayer(bitmap, strIconOver, strIconOverColor);

    // overlay 2 icon
    addIconLayer(bitmap, strIconOver2, strIconOver2Color);
}
Exemple #12
0
void	cbUpdateMouseListenerConfig(CConfigFile::CVar &var)
{
	if (var.Name == "MouseInvert") MouseListener->setInvertMouseMode(var.asInt() != 0);
	else if (var.Name == "MouseZoomStep") MouseZoomStep = var.asFloat ();
	else if (var.Name == "ViewLagBehind") MouseListener->setViewLagBehind(var.asFloat ());
	else if (var.Name == "ViewHeight") MouseListener->setViewHeight(var.asFloat ());
	else if (var.Name == "ViewTargetHeight") MouseListener->setViewTargetHeight(var.asFloat ());
	else nlwarning ("Unknown variable update %s", var.Name.c_str());
}
// this function will be called when the variable var12 will be modified by
// an external program
void var12Callback (CConfigFile::CVar &var)
{
	stringstream str;
	
	for (uint i = 0; i < var.size (); i++)
		str << var.asInt (i) << " ";

	nlinfo("%s modified, new value: %s\n", var.Name.c_str (), str.str().c_str());
}
Exemple #14
0
void				cbSimVar (CConfigFile::CVar &var)
{
	     if (var.Name == "SimInLag") CUdpSimSock::_InLag = var.asInt ();
	else if (var.Name == "SimInPacketLost") CUdpSimSock::_InPacketLoss = uint8(var.asInt ());
	else if (var.Name == "SimOutLag") CUdpSimSock::_OutLag = var.asInt ();
	else if (var.Name == "SimOutPacketLost") CUdpSimSock::_OutPacketLoss = uint8(var.asInt ());
	else if (var.Name == "SimOutPacketDuplication") CUdpSimSock::_OutPacketDuplication = uint8(var.asInt ());
	else if (var.Name == "SimOutPacketDisordering") CUdpSimSock::_OutPacketDisordering = uint8(var.asInt ());
	else nlstop;
}
/*
 * Restore Shard Open state from config file or from file if found
 */
void cbRestoreShardOpen(CMessage &msgin, const std::string &serviceName, TServiceId  sid)
{
	// first restore state from config file
	CConfigFile::CVar*	var = IService::getInstance()->ConfigFile.getVarPtr("ShardOpen");
	if (var != NULL)
	{
		setShardOpenState((TShardOpenState)var->asInt());
	}

	// then restore state from state file, if it exists
	cbShardOpenStateFile(ShardOpenStateFile);
}
	/// Set expected instances. Ex: { "TICKS", "FS", "FS", "FS" }
	void		setExpectedInstances( CConfigFile::CVar& var )
	{
		// Reset "expected" counters (but don't clear the map, keep the running instances)
		CInstances::iterator ici;
		for ( ici=_Instances.begin(); ici!=_Instances.end(); ++ici )
		{
			(*ici).second.Expected = 0;
		}
		// Rebuild "expected" counters
		for ( uint i=0; i!=var.size(); ++i )
		{
			++_Instances[var.asString(i)].Expected;
		}
	}
Exemple #17
0
// compile the source files to generate new object files
void CAIManager::compile()
{
	// get the file names of input and output files
	std::string srcFile=CAIFiles::fullSrcFileName(id());
	std::string objFile=CAIFiles::fullObjFileName(id());

	// make sure this file isn't in the ignore list
	CConfigFile::CVar *varPtr;
	varPtr=IService::getInstance()->ConfigFile.getVarPtr(std::string("IgnorePrimitives"));
	if (varPtr==NULL)
	{
		nlwarning("Cannot compile file '%s' as IgnorePrimitives variable not found in .cfg file: Please add 'IgnorePrimitives={\"\"};' and try again",CAIFiles::fullSrcFileName(id()).c_str());
		return;
	}
	for (uint i=0;i<varPtr->size();++i)
		if (CAIFiles::srcName(id())==CFile::getFilenameWithoutExtension(varPtr->asString(i)))
		{
			nlinfo("Skipping file in .cfg ignoreList: %s",CAIFiles::fullSrcFileName(id()).c_str());
			return;
		}

	// compile the input file
	nlinfo("Compile %s => %s",srcFile.c_str(),objFile.c_str());
	CAIDSActions::CurrentManager=id();
	AI_SHARE::parsePrimFile(srcFile.c_str());

	// make sure this file isn't in the ignore list (if the compiler found nothing interesting it will have been added)
	varPtr=IService::getInstance()->ConfigFile.getVarPtr(std::string("IgnorePrimitives"));
	for (uint i=0;i<varPtr->size();++i)
		if (CAIFiles::srcName(id())==CFile::getFilenameWithoutExtension(varPtr->asString(i)))
		{
			nlinfo("- Skipping file as it has just been added to .cfg ignoreList: %s",CAIFiles::fullSrcFileName(id()).c_str());
			return;
		}

	// write the output file
	CAIFiles::writeObjFile(id());

	// write the binary output file (for debugging only)
	NLMISC::COFile file;
	if (file.open(objFile+"_out"))
	{
		std::string s;
		MgrDfnRootNode.serialToString(s);
		file.serial(s);
		file.close();
	}
	else
		nlwarning("CAIManager::compile(): Failed to open the output file: %s",(objFile+"_out").c_str());
}
/** Generate list of spell
  */
static void generateSpellList(CConfigFile &cf, const std::string &sheetName)
{
	CConfigFile::CVar *spellList = cf.getVarPtr("spell_list");
	if (!spellList)
	{
		nlwarning("Can't read spell list");
		return;
	}	
	COFile f;
	if (!f.open(sheetName, false, true))
	{
		nlwarning("Can't write %s", sheetName.c_str());
		return;
	}
	try
	{	
		COXml xmlStreamOut;
		xmlStreamOut.init(&f);
		xmlStreamOut.xmlPush("FORM");
		IStream &xmlStream = xmlStreamOut;
		xmlStream.xmlPush("STRUCT");
		xmlStream.xmlPushBegin("ARRAY");
			xmlStream.xmlSetAttrib("Name");
			std::string name = "List";
			xmlStream.serial(name);					
		xmlStream.xmlPushEnd();				
		for(uint k = 0; k < (uint) spellList->size(); ++k)
		{
			std::vector<std::string> result;
			NLMISC::splitString(spellList->asString(k), "|", result);
			if (result.size()  < 2)
			{
				nlwarning("Should provide at list spell name and id");
			}
			xmlStream.xmlPush("STRUCT");				
				writeAtom(xmlStream, "ID", result[1]);
				writeAtom(xmlStream, "SheetBaseName", result[0]);
			xmlStream.xmlPop();
		}
		xmlStream.xmlPop(); // STRUCT
		xmlStream.xmlPop(); // FORM
	}
	catch(const EStream &)
	{
		nlwarning("Cant write %s", sheetName.c_str());
	}
}
//-----------------------------------------------------------------------------
void CBackupService::init()
{
	FileManager.init();

	setUpdateTimeout(100);
	_SaveStall = false;

	// set the connection and disconnection callbacks
	CUnifiedNetwork::getInstance()->setServiceUpCallback( string("*"), cbConnection, 0);
	CUnifiedNetwork::getInstance()->setServiceDownCallback( string("*"), cbDisconnection, 0);

	CUnifiedNetwork::getInstance()->setServiceUpCallback( string("BS"), cbConnection, 0);
	CUnifiedNetwork::getInstance()->setServiceDownCallback( string("BS"), cbDisconnection, 0);

	// Init the sheet Id 
	CSheetId::init(false);

	if (!MasterBSHost.get().empty())
	{
		IService::getInstance()->addStatusTag("SlaveMode");
		IService::getInstance()->setCurrentStatus("WaitingMaster");

		BSIsSlave = true;
		FileManager.forbidStall();
		// I'm a slave, try to contact master
		string	host = MasterBSHost;
		if (host.find (":") == string::npos)
			host += ":49990";

		CUnifiedNetwork::getInstance()->addService ("BS", CInetAddress(host));
	}

	// set the initial read state from the config file
	CConfigFile::CVar *readState = ConfigFile.getVarPtr("BSReadState");
	if (readState != NULL)
		BSReadState = readState->asBool();


	initWebConnection();

	_CallbackServer = new NLNET::CCallbackServer;
	_CallbackServer->addCallbackArray(cbSyncArray, sizeofarray(cbSyncArray));
	// open the layer 3 callback server if required
	if (L3ListeningPort != 0)
		_CallbackServer->init(L3ListeningPort);
}
// @{
// \name Overload for IPluginCallback
void		CPrimitivePlugin::init(IPluginAccess *pluginAccess)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	AfxEnableControlContainer();
	_PluginAccess = pluginAccess;

	string packedFileName("primitive_plugin.packed_sheets");

	vector<string>	paths;
	string sheetIdPath;

	// add the search path
	CConfigFile &cf = pluginAccess->getConfigFile();
	CConfigFile::CVar *pv = cf.getVarPtr("PrimitivePluginPath");
	if (pv)
	{
		for (uint i=0; i<pv->size(); ++i)
			paths.push_back(pv->asString(i));
	}
	// add the sheetId file
	pv = cf.getVarPtr("PrimitivePluginSheetId");
	sheetIdPath = pv->asString();

	// Init the sheet id
	CPath::addSearchFile(sheetIdPath);
	CSheetId::init(false);

	// Read the sheets
	if (NLMISC::CFile::fileExists(packedFileName))
		loadForm("creature", packedFileName, _CreatureInfos, false, false);
	else
	{
		for (uint i=0; i<paths.size(); ++i)
		{
			CPath::addSearchPath(paths[i], true, false);
		}

		// build the packed sheet
		loadForm("creature", packedFileName, _CreatureInfos, true, false);
	}

	vector<string>	classNames;
	classNames.push_back("npc_bot");
	_PluginAccess->registerPrimitiveDisplayer(this, classNames);
}
Exemple #21
0
CRGBA CConfiguration::getValue(const string &varName, const CRGBA &defaultValue)
{
	if (m_ConfigFile.exists(varName)) 
	{
		return getValue(m_ConfigFile.getVar(varName), defaultValue);
	}
	else
	{
		// create a new value only if one doesn't exist
		CConfigFile::CVar varToCopy;
		varToCopy.forceAsInt(defaultValue.R);
		varToCopy.setAsInt(defaultValue.G, 1);
		varToCopy.setAsInt(defaultValue.B, 2);
		varToCopy.setAsInt(defaultValue.A, 3);
		m_ConfigFile.insertVar(varName, varToCopy);
	}
	return defaultValue;
}
Exemple #22
0
void CWorldEditorApp::loadPlugins()
{
	// 1st load the plugin configuration file
//	char curDir[MAX_PATH];
//	GetCurrentDirectory (MAX_PATH, curDir);

	PluginConfig.load((ExePath+"/world_editor_plugin.cfg").c_str());

	// enumerate the plugin variable.
	CConfigFile::CVar *plugins = PluginConfig.getVarPtr("PluginsLibrary");

	if (plugins != 0)
	{
		for (uint i=0; i<plugins->size(); ++i)
		{
			string libname = plugins->asString(i)+nlLibSuffix+".dll";

			//vl HMODULE h = AfxLoadLibrary(libname.c_str());
			NL_LIB_HANDLE h = nlLoadLibrary(libname.c_str());
			if (h == NULL)
				continue;

			//FCreateSoundPlugin *pf = (FCreateSoundPlugin*) GetProcAddress(h, "createSoundPlugin");
			//JC: switch to the generic call as soon as possible
			//vl FCreatePlugin *pf = (FCreatePlugin*) GetProcAddress(h, "createPlugin");
			FCreatePlugin *pf = (FCreatePlugin*) nlGetSymbolAddress(h, "createPlugin");

			if (pf == NULL)
				continue;

			// ok, the plugin is loaded.
			IPluginCallback *pcb = (IPluginCallback*) pf();

			if (pcb == 0)
				continue;

			nlinfo("Plugins '%s' loaded", libname.c_str());
			Plugins.push_back(pcb);

			// init the plugin.
			pcb->init(getMainFrame());
		}
	}
}
Exemple #23
0
void CConfiguration::cfcbLogFilter(CConfigFile::CVar &var)
{
	// from nel/net/service.cpp	
	CLog *log = NULL;
	if (var.Name == "NegFiltersDebug") log = DebugLog;
	else if (var.Name == "NegFiltersInfo") log = InfoLog;
	else if (var.Name == "NegFiltersWarning") log = WarningLog;
	else if (var.Name == "NegFiltersAssert") log = AssertLog;
	else if (var.Name == "NegFiltersError") log = ErrorLog;
	else nlstop;

	// remove all old filters from config file
	CConfigFile::CVar &oldvar = m_ConfigFile.getVar(var.Name);
	for (uint j = 0; j < oldvar.size(); j++)
		log->removeFilter(oldvar.asString(j).c_str());
	
	// add all new filters from config file
	for (uint i = 0; i < var.size(); i++)
		log->addNegativeFilter(var.asString(i).c_str());
}
Exemple #24
0
CRGBA CConfiguration::getValue(const CConfigFile::CVar &var, const CRGBA &defaultValue)
{
	if (var.size() >= 3)
	{
		if (var.size() > 4) nlwarning("RGBA value in config value '%s' is too long, ignoring unused values");
		return CRGBA(var.asInt(0), var.asInt(1), var.asInt(2), var.size() >= 4 ? var.asInt(3) : 255);
	}
	nlwarning("Invalid RGBA value in config value '%s', reverting to default { %i, %i, %i, %i }", var.Name.c_str(), (sint)defaultValue.R, (sint)defaultValue.G, (sint)defaultValue.B, (sint)defaultValue.A);	
	return defaultValue;
}
Exemple #25
0
void CConfiguration::init()
{	
	// verify data
	nlassert(!m_ConfigCallbacks.size());
	
	// load config
	m_ConfigFile.load(NLQT_CONFIG_FILE);
	
	// log config
	CConfiguration::setAndCallback("NegFiltersDebug", CConfigCallback(this, &CConfiguration::cfcbLogFilter));
	CConfiguration::setAndCallback("NegFiltersInfo", CConfigCallback(this, &CConfiguration::cfcbLogFilter));
	CConfiguration::setAndCallback("NegFiltersWarning", CConfigCallback(this, &CConfiguration::cfcbLogFilter));
	CConfiguration::setAndCallback("NegFiltersAssert", CConfigCallback(this, &CConfiguration::cfcbLogFilter));
	CConfiguration::setAndCallback("NegFiltersError", CConfigCallback(this, &CConfiguration::cfcbLogFilter));

	// set the search paths (kinda important)
	CConfigFile::CVar *var;
	var = m_ConfigFile.getVarPtr("SearchPaths");
	uint varsize = var->size();
	for (uint i = 0; i < varsize; ++i)
		CPath::addSearchPath(var->asString(i), true, false);
	var = m_ConfigFile.getVarPtr("RemapExtensions");
	varsize = var->size();
	for (uint i = 0; i < varsize; i += 2)
		CPath::remapExtension(var->asString(i), var->asString(i + 1), true);
}
Exemple #26
0
void cbUpdateCompass (CConfigFile::CVar &var)
{
	if (var.Name == "CompassPosX") CompassPosX = var.asFloat ();
	else if (var.Name == "CompassPosY") CompassPosY = var.asFloat ();
	else if (var.Name == "CompassRadius") CompassRadius = var.asFloat ();
	else if (var.Name == "CompassColor") 
	{
		CompassColor.set(var.asInt(0), var.asInt(1), var.asInt(2), var.asInt(3));
		CompassMaterial.setColor(CompassColor);
	}
	else nlwarning ("Unknown variable update %s", var.Name.c_str());
}
Exemple #27
0
bool CConfiguration::init()
{
	nlassert(!ConfigFile); ConfigFile = new CConfigFile(); nlassert(ConfigFile);
	ConfigFile->load(SBCLIENT_CONFIG_FILE);

	// set the search paths (kinda important)
	CConfigFile::CVar *var;
	var = ConfigFile->getVarPtr("SearchPaths");
	uint varsize = var->size();
	for (uint i = 0; i < varsize; ++i)
		CPath::addSearchPath(var->asString(i), true, false);
	var = ConfigFile->getVarPtr("RemapExtensions");
	varsize = var->size();
	for (uint i = 0; i < varsize; i += 2)
		CPath::remapExtension(var->asString(i), var->asString(i + 1), true);

	return true;
}
Exemple #28
0
void cbUpdateSkillsDisplay (CConfigFile::CVar &var)
{
	if (var.Name == "SkillsDisplayState") SkillsDisplayState = var.asInt ();
}
//****************************************************************************************************************************
int main(int argc, char* argv[])
{
	if (argc < 2)
	{
		nlwarning("Usage : %s config_file_name.cfg", argv[0]);
		return -1;
	}
	CConfigFile cf;
	try
	{	
		cf.load(argv[1]);
	}
	catch(const NLMISC::EConfigFile &)
	{
		nlwarning("Error in config file %s", argv[1]);
		return -1;
	}	
	catch(...)
	{
		nlwarning("Can't read config file %s", argv[1]);
		return -1;
	}
	// output for sheets
	std::string outputPath;
	CConfigFile::CVar *outputPathVar = cf.getVarPtr("output_path");
	if (outputPathVar)
	{
		outputPath = outputPathVar->asString() + "/";
	}
	// output for 'levels' parents
	std::string levelParentsPath;
	CConfigFile::CVar *levelParentsPathVar = cf.getVarPtr("level_parents");
	if (levelParentsPathVar)
	{
		levelParentsPath = levelParentsPathVar->asString() + "/";
	}
	// output for projectile parents
	std::string projectileParentsPath;
	CConfigFile::CVar *projectileParentsPathVar = cf.getVarPtr("projectile_base");
	if (projectileParentsPathVar)
	{
		projectileParentsPath= projectileParentsPathVar->asString() + "/";
	}	
	// output for 'projectile by level and mode' parents
	std::string projectileByLevelAndModeParentsPath;
	CConfigFile::CVar *projectileByLevelAndModeParentsPathVar = cf.getVarPtr("projectile_by_level_and_mode_parents");
	if (projectileByLevelAndModeParentsPathVar)
	{
		projectileByLevelAndModeParentsPath = projectileByLevelAndModeParentsPathVar->asString() + "/";
	}
	// output for 'base spells' parents
	std::string baseSpellPath;
	CConfigFile::CVar *baseSpellPathVar = cf.getVarPtr("spell_base");
	if (baseSpellPathVar)
	{
		baseSpellPath = baseSpellPathVar->asString() + "/";
	}
	// output for 'spell by levels' parents
	std::string spellByLevelParentsPath;
	CConfigFile::CVar *spellByLevelParentsPathVar = cf.getVarPtr("spell_by_level_parents");
	if (spellByLevelParentsPathVar)
	{
		spellByLevelParentsPath = spellByLevelParentsPathVar->asString() + "/";
	}
	// output for 'final spell'
	std::string finalSpellPath;
	CConfigFile::CVar *finalSpellPathVar = cf.getVarPtr("final_spells");
	if (finalSpellPathVar)
	{
		finalSpellPath = finalSpellPathVar->asString() + "/";
	}
	


	// read number of levels
	CConfigFile::CVar *numLevelVar = cf.getVarPtr("num_levels");
	if (!numLevelVar)
	{
		nlwarning("Can't read number of spell levels");
		return -1;
	}
	uint numSpellLevels = numLevelVar->asInt();

	std::vector<CUserParams> userParams(numSpellLevels);

	// read user params set for each level
	for(uint level = 0; level < numSpellLevels; ++level)
	{
		std::string varName = toString("user_params_level%d", (int) (level + 1));
		CConfigFile::CVar *up = cf.getVarPtr(varName);
		if (!up)
		{
			nlwarning("Can't read var %s", varName.c_str());
		}
		else
		{
			for(uint k = 0; k < CUserParams::NumUserParams; ++k)
			{
				userParams[level].UserParam[k] = up->asString(k);
			}
		}		
	}

	// read types of spells (offensif, curatif ...)
	CConfigFile::CVar *spellTypesList = cf.getVarPtr("spell_types"); 
	if (!spellTypesList)
	{
		nlwarning("Can't read types of spells");
		return -1;
	}
	// read modes of spells
	CConfigFile::CVar *spellModesList = cf.getVarPtr("spell_modes");

	// read name of ps for projectiles
	std::vector<std::string> projPSNames;
	projPSNames.resize(spellTypesList->size() * spellModesList->size());
	CConfigFile::CVar *projectileNames = cf.getVarPtr("projectile_fx");
	if (projectileNames)
	{
		for(uint k = 0; k < (uint) projectileNames->size(); ++k)
		{
			// entry are expected to have the following form : 
			// "type|mode|fx_name.ps"
			std::vector<std::string> params;
			NLMISC::splitString(projectileNames->asString(k), "|", params);
			if (params.size() != 3)
			{
				nlwarning("Bad param for projectile ps name : %s", projectileNames->asString(k).c_str());
			}
			else
			{
				bool found = false;
				// find the mode				
				for (uint mode = 0; mode < (uint) spellModesList->size(); ++mode)
				{
					if (spellModesList->asString(mode) == params[1])
					{						
						for (uint type = 0; type < (uint) spellTypesList->size(); ++type)
						{
							if (spellTypesList->asString(type) == params[0])
							{
								projPSNames[type + mode * spellTypesList->size()] = params[2];
								//nlwarning("%s : found", projectileNames->asString(k).c_str());
								found = true;
								break;
							}
						}
						if (found) break;
					}
				}
				//if (!found) nlwarning("%s : not found", projectileNames->asString(k).c_str());
			}			
		}
	}

	nlinfo("Generate projectiles parent sheets...");
	// gen projectiles base sheet
	CSpellSheet baseProjectileSheet;
	baseProjectileSheet.writeSheet(outputPath + projectileParentsPath + "_projectile_base.spell");	
	// gen projectiles parent sheets
	for(uint type = 0; type < (uint) spellTypesList->size(); ++type)
	{
		for(uint mode = 0; mode < (uint) spellModesList->size(); ++mode)
		{
			std::string sheetName = "_projectile_" + spellTypesList->asString(type) + "_" + spellModesList->asString(mode) + ".spell";
			CSpellSheet ss;
			ss.Parents.push_back("_projectile_base.spell");
			// affect ps name if known
			ss.Projectile.FX[0].PSName = projPSNames[type + mode * spellTypesList->size()];
			ss.writeSheet(outputPath + projectileParentsPath + sheetName);			
		}
	}
	
	nlinfo("Generate sheets by level...");
	// generate sheets by level
	for(uint level = 0; level < numSpellLevels; ++level)
	{		
		// gen projectiles by level sheets (parent sheets)
		std::string sheetName = toString("_projectile_lvl%d.spell", (int) (level + 1));
		CSpellSheet projectileSheet;
		projectileSheet.Projectile.setUserParams(userParams[level]);
		projectileSheet.writeSheet(outputPath + levelParentsPath + sheetName);
		// gen impact level sheets
		sheetName = toString("_impact_lvl%d.spell", (int) (level + 1));
		CSpellSheet impactSheet;
		impactSheet.Impact.setUserParams(userParams[level]);
		impactSheet.writeSheet(outputPath + levelParentsPath + sheetName);
		
	}

	nlinfo("Generate projectile list (by mode, type and levels)...");
	// generate projectile list (by mode, type and levels)
	for(uint type = 0; type < (uint) spellTypesList->size(); ++type)
	{
		for(uint mode = 0; mode < (uint) spellModesList->size(); ++mode)
		{
			for(uint level = 0; level < (uint) numSpellLevels; ++level)
			{			
				CSpellSheet ss;
				ss.Parents.resize(2);
				ss.Parents[0] = toString("_projectile_lvl%d.spell", (int) (level + 1)); // inherit level
				ss.Parents[1] = "_projectile_" + spellTypesList->asString(type) + "_" + spellModesList->asString(mode) + ".spell"; // inherit mode and type
				std::string sheetName = "_projectile_" + spellTypesList->asString(type) + "_" + spellModesList->asString(mode) + toString("_lvl%d.spell", (int) (level + 1));
				ss.writeSheet(outputPath + projectileByLevelAndModeParentsPath + sheetName);			
			}
		}
	}
	//
	nlinfo("Generate spell list...");
	// read list of spells
	// the string format for spells is : "sheet_name|ps_name"
	// the name of the particle system is optionnal
	CConfigFile::CVar *spellList = cf.getVarPtr("spell_list");
	if (!spellList)
	{
		nlwarning("Can't read spell list");
		return -1;
	}
	for(uint k = 0; k < (uint) spellList->size(); ++k)
	{
		std::string spellName = spellList->asString(k);
		std::vector<std::string> result;
		NLMISC::splitString(spellName, "|", result);
		if (result.size()  < 3)
		{
			nlwarning("Should provide at least spell name, id and mode");
		}
		else
		{		
			// generate parent sheet
			CSpellSheet baseSpellSheet;
			if (result.size() > 3)
			{			
				baseSpellSheet.Impact.FX[0].PSName = result[3];
			}
			baseSpellSheet.writeSheet(outputPath + baseSpellPath + "_" + result[0] + ".spell");
			// generate child sheet
			// - by spell level
			// - by spell type (chain, bomb, spray ...)

			// save spells by level
			for(uint level = 0; level < numSpellLevels; ++level)
			{
				CSpellSheet leveledSpell;
				leveledSpell.Parents.resize(2);
				leveledSpell.Parents[0] = "_" + result[0] + ".spell";
				leveledSpell.Parents[1] = toString("_impact_lvl%d.spell", (int) (level + 1));
				leveledSpell.writeSheet(outputPath + spellByLevelParentsPath + "_" + result[0] + toString("_lvl%d.spell", (int) (level + 1)));
			}

			// save spell with good projectile and level
			for(uint level = 0; level < numSpellLevels; ++level)
			{
				for(uint mode = 0; mode < (uint) spellModesList->size(); ++mode)
				{
					CSpellSheet finalSheet;
					finalSheet.Parents.resize(2);
					finalSheet.Parents[0] = "_" + result[0] + toString("_lvl%d.spell", (int) (level + 1));
					finalSheet.Parents[1] = "_projectile_" + result[2] + "_" + spellModesList->asString(mode) + toString("_lvl%d.spell", (int) (level + 1));
					//finalSheet.writeSheet(outputPath + finalSpellPath + result[0] + toString("_lvl%d_", (int) (level + 1)) + result[2] + "_" + spellModesList->asString(mode) + ".spell");
					finalSheet.writeSheet(outputPath + finalSpellPath + result[0] + "_" + spellModesList->asString(mode) + toString("_lvl%d", (int) (level + 1)) + ".spell");
				}
			}
		}
	}
	// generate spell list with their ids
	CConfigFile::CVar *spellListFile = cf.getVarPtr("spell_list_file");
	if (spellListFile)
	{	
		generateSpellList(cf, outputPath + spellListFile->asString());
	}
	nlinfo("Done");
	return 0;
}
void cbUpdateInventoryDisplay (CConfigFile::CVar &var)
{
	if (var.Name == "InventoryState") InventoryState = var.asInt ();
}