Hi to all.
I have to backup my npcdesc.cfg using a script.
I want to create a new datafile ad to set it as the cfgfile in order
to modify it using a gmtool and, finally, to update the original
cfgfile by ftp (not with script).
My question is:
How can i set the name of the elements in a datafile?
I do not want them to be "element" but "npctemplate" (like the
original npcdesc.cfg
Thanks
Gnafu
How to copy a cfg file in a datafile
-
Marilla
Hi there;
To my knowledge, it is impossible to do exactly what you want: Change the indicators on the elements in the data file to make them compatable.
However...
If I understand what you want to do here, let me re-state it for clarity; maybe that will get the creative juices flowing, and we can come up with some solution here.
You want to be able to modify NPC definitions from within POL, basically. Because you know that config files cannot be altered from within POL, you were thinking of using data files, which CAN be altered, and then basically manually 'copy' the data files over top of the config files... am I right?
Here's an idea I have, then: How about, instead of creating data files, why not create a "npcdesccopy.cfg" file in script; Have an interface for editing the NPCs you want, and it then saves the new values to the new npcdesccopy.cfg file. Also have some mechanism for allowing your script to save an array of NPCdesc entries you want it to DELETE.
Then, when you are done editing in POL, have a script that runs through all the REST of the npcdesc entries (ones you did not edit), and copy over all the ones that you did not mark to delete.
Once you are done with that process (be ===100% sure=== you have the scripting that COPIES over all the unedited ones!!!), you can then use FTP, or a shell program (see my idea post on the 096 ideas board!) to copy over all instances of npcdesccopy.cfg over top of the original.
To my knowledge, it is impossible to do exactly what you want: Change the indicators on the elements in the data file to make them compatable.
However...
If I understand what you want to do here, let me re-state it for clarity; maybe that will get the creative juices flowing, and we can come up with some solution here.
You want to be able to modify NPC definitions from within POL, basically. Because you know that config files cannot be altered from within POL, you were thinking of using data files, which CAN be altered, and then basically manually 'copy' the data files over top of the config files... am I right?
Here's an idea I have, then: How about, instead of creating data files, why not create a "npcdesccopy.cfg" file in script; Have an interface for editing the NPCs you want, and it then saves the new values to the new npcdesccopy.cfg file. Also have some mechanism for allowing your script to save an array of NPCdesc entries you want it to DELETE.
Then, when you are done editing in POL, have a script that runs through all the REST of the npcdesc entries (ones you did not edit), and copy over all the ones that you did not mark to delete.
Once you are done with that process (be ===100% sure=== you have the scripting that COPIES over all the unedited ones!!!), you can then use FTP, or a shell program (see my idea post on the 096 ideas board!) to copy over all instances of npcdesccopy.cfg over top of the original.
YesMarilla wrote:Hi there;
You want to be able to modify NPC definitions from within POL, basically. Because you know that config files cannot be altered from within POL, you were thinking of using data files, which CAN be altered, and then basically manually 'copy' the data files over top of the config files... am I right?
What do you mean with "create a "npcdesccopy.cfg" file in script;" ?Marilla wrote:Here's an idea I have, then: How about, instead of creating data files, why not create a "npcdesccopy.cfg" file in script; Have an interface for editing the NPCs you want, and it then saves the new values to the new npcdesccopy.cfg file. Also have some mechanism for allowing your script to save an array of NPCdesc entries you want it to DELETE.
Sorry, but i'm not english, it's hard to understand your ideaMarilla wrote:Then, when you are done editing in POL, have a script that runs through all the REST of the npcdesc entries (ones you did not edit), and copy over all the ones that you did not mark to delete.
Once you are done with that process (be ===100% sure=== you have the scripting that COPIES over all the unedited ones!!!), you can then use FTP, or a shell program (see my idea post on the 096 ideas board!) to copy over all instances of npcdesccopy.cfg over top of the original.
BTW, i solved in this way:
I upload a datafile identical to the npcdesc.
I use my script to show cfgfile's and datafile's value of the same NPC and to modify the datafile
The rest is manual work
But i have another problem:
I have created a file called npcdesc.txt in the c:\pol\data directory
When i try to read it by
Code: Select all
var datafile:= OpenDataFile( "npcdesc" );where must i put it? or how must i call it?
and, must i unload it every time i try to re-open it with the function above?
Thanks
You can use this include:
Code: Select all
use uo;
use os;
use basic;
use cfgfile;
use datafile;
/*===============================================================
* Current Version
* DATAFILE.INC - v2.0
* include ":datafile:include/datafile";
*
* -- Revision v2.0 --
* Austin:
* Changed:
* Now a package, rather than loose include file.
* Cleaned up to match new distro comment, code and package directory structure standards.
*
* -- Revision 1.3 --
* Austin:
* Added:
* Global variable called 'DF_DEBUG_MODE'
* Setting it to 0 in your script will make the functions
* no longer SysLog() information to the console. By default
* it is enabled.
*
* Fixed:
* Bug in DFSetProp() when I improved the .errortext return stuff.
*
* -- Revision 1.2 --
* Austin
* Added:
* Flags option for DFOpenDataFile()
* DFGetElemNames()
*
* Changed:
* Changed the error stuff, to return .errortext
===============================================================*/
/////////////////////////////////////////////////////////////////
// * Function List *
// DFFindElement(byref file_ref, elem_name, create)
// DFGetElemNames(byref file_ref)
// DFGetElemProps(elem_ref)
// DFGetProp(byref elem_ref, prop_name, create, assign_val)
// DFOpenDataFile(file_name, create, flags)
//
// CfgToDF(cfg_name, df_name, propnames)
// DFToCfg(df_name, cfg_name)
//
/////////////////////////////////////////////////////////////////
// * Internal/Private Function List *
// DF_OutPut(text)
//
/////////////////////////////////////////////////////////////////
// * Global Variables *
//
// Datafile.em constants
// const DF_KEYTYPE_STRING := 0x00; // default
// const DF_KEYTYPE_INTEGER := 0x01;
//
// Determines if a file or elem will be created when a read attempt is made.
const DF_NO_CREATE := 0;
const DF_CREATE := 1;
// Set to 0 in your script to turn off SysLog() calls.
var DF_DEBUG_MODE := 1;
/*
* DFOpenDataFile(filename, create, flags)
*
* Purpose
* Creates a datafile handler.
*
* Parameters
* filename: Path and name of the data file. (Example ":pkg-name:file-name")
* create: Creation flags:
* DF_NO_CREATE Will return an error if the datafile does not exist. *Default
* DF_CREATE Will create the datafile if it does not exist.
* flags: Datafile.em flags:
* DF_KEYTYPE_STRING Elem names will be handled as strings.
* DF_KEYTYPE_INTEGER Elem names will be handled as integers.
*
* Return value
* A datafile reference.
*
*/
function DFOpenDataFile(file_name, create:=DF_NO_CREATE, flags:=DF_KEYTYPE_STRING)
var data_file := OpenDataFile(file_name);
if ( (!data_file) && (create) )
DF_OutPut("Creating data file: " + file_name);
CreateDataFile(file_name, flags);
data_file := OpenDataFile(file_name);
endif
if ( data_file )
return data_file;
elseif ( create )
var errmsg := error;
errmsg.+errortext := "Could not open " + file_name + ":" + data_file.errortext;
DF_OutPut(errmsg.errortext);
return errmsg;
endif
endfunction
/*
* DFGetElemNames(byref file_ref)
*
* Purpose
* Retrieves a list of all elem names that are in a data file.
*
* Parameters
* file_ref: The datafile to retrieve the elem names in.
*
* Return value
* An array of strings or integers.
*
*/
function DFGetElemNames(byref file_ref)
var elem_keys := file_ref.keys();
if ( elem_keys == error )
var errmsg := error;
errmsg.+errortext := "Could not return elem keys :"+elem_keys.errortext;
DF_OutPut(errmsg.errortext);
return errmsg;
else
return elem_keys;
endif
endfunction
/*
* DFFindElement(byref file_ref, elem_name, create)
*
* Purpose
* Creates a datafile elem handler.
*
* Parameters
* file_ref: Data file to retrieve/create the element in.
* elem_name: Name of the element to retrieve.
* create: Creation flags:
* DF_NO_CREATE Will return an error if the data elem does not exist. *Default
* DF_CREATE Will create the data elem if it does not exist.
*
* Return value
* A data file element reference.
*
*/
function DFFindElement(byref file_ref, elem_name, create:=DF_NO_CREATE)
var temp := file_ref.FindElement( cstr(elem_name) );
if (!temp && create)
DF_OutPut("Creating elem: " + cstr(elem_name) );
file_ref.CreateElement( cstr(elem_name) );
temp := file_ref.FindElement( cstr(elem_name) );
endif
if ( temp )
return temp;
elseif (create)
var errmsg := error;
errmsg.+errortext := "Could not open data elem " + elem_name + ":" + temp.errortext;
DF_OutPut(errmsg.errortext);
return errmsg;
endif
endfunction
/*
* DFGetElemProps(byref elem_ref)
*
* Purpose
* Retrieves a list of all prop names that are in a data elem.
*
* Parameters
* elem_ref: The data elem to retrieve the property names in.
*
* Return value
* An array of strings.
*
*/
function DFGetElemProps(elem_ref)
var prop_names := elem_ref.PropNames();
if ( prop_names == error )
var errmsg := error;
errmsg.+errortext := "Could not return prop names :"+prop_names.errortext;
DF_OutPut(errmsg.errortext);
return errmsg;
else
return prop_names;
endif
endfunction
/*
* DFGetProp(byref elem_ref, prop_name, create, assign_val)
*
* Purpose
* Retrieves the information in a cprop, or assigns it a value if told to do-so.
*
* Parameters
* elem_ref: The data elem to retrieve the property from.
* prop_name: The name of the property to retrieve.
* create: Creation flags:
* DF_NO_CREATE Will return an error if the property does not exist. *Default
* DF_CREATE Will create the property if it does not exist and an assign value is set.
* assign_val: Value to set the property to if it is created.
*
* Return value
* The value of the property.
*
*/
function DFGetProp(byref elem_ref, prop_name, create:=DF_NO_CREATE, assign_val:=0)
var temp := elem_ref.GetProp(prop_name);
if ( (temp==error) && (create) )
elem_ref.SetProp(prop_name, assign_val);
temp := elem_ref.GetProp(prop_name);
endif
if ( temp || (create) && (!assign_val) )
// Second case is for creating and returning
// what ever you get. Used for cases where the
// value is '0' but not an error.
return temp;
elseif (create)
var errmsg := error;
errmsg.+errortext := "Could not read data file property " + prop_name + ":" + temp.errortext;
DF_OutPut(errmsg.errortext);
return errmsg;
endif
endfunction
//===============================================================
/*
* -=Experimental Function=-
* Convert a datafile to a config file.
*
* DFToCfg( <string>, <string> )
* 1. Pass two strings.
* One string is the name of the datafile.
* The other string is the name of the config file.
* Note: you can also pass a datafile reference and/or a cfg file reference instead of strings.
*
* 2. The datafile's properties will be broken down and copied into the config file.
* All of the datafiles CProp values will go through the Pack() function to ensure
* they will go into the config file correctly.
*
* This function does not do any error checking so when you write to a config file
* it is best to make sure the cfg file is blank so you dont risk duplicate keys.
*
*/
function DFToCfg(df_name, cfg_name)
if ( lower(TypeOf(df_name))["string"] )
df_name := DFOpenDataFile(df_name, DF_CREATE);
endif
if ( lower(TypeOf(cfg_name)) != "string" )
var errmsg := error;
errmsg.+errortext := "DFToCfg() cfg_name parameter passed was not a string.";
DF_OutPut(errmsg.errortext);
return errmsg;
endif
foreach elem_name in DFGetElemNames(df_name)
var elem := DFFindElement(df_name, elem_name);
var elem_info := array;
var prop_info := array;
prop_info.+name;
prop_info.+value;
foreach prop_name in DFGetElemProps(elem)
prop_info.name := prop_name;
prop_info.value := Pack(DFGetProp(elem, prop_name));
sleepms(2);
endforeach
AppendConfigFileElem(cfg_name, "Elem", elem_name, elem_info);
sleepms(2);
endforeach
return 1;
endfunction
/*
* -=Experimental Function=-
* Convert a config file to a data file.
*
* CfgToDF( <string>, <string>, <array[strings]>)
* 1. Pass a config file name, datafile name, and the lines in the elems to copy over.
* An example would be CfgToDF("itemdesc", "archive", {"Name", "Desc", "Graphic", "Color"})
* Note: You can also pass a datafile reference instead of a string.
* The config file in this one *must* be passed as a string though to use
* the AppendConfigFileElem() function in cfgfile.em
*
* 2. The config file's elems will be broken down. If it has any lines in that elem that match
* the lines passed in 'propnames' they will be copied over into the datafile.
*
* If there are multiple entries in the config file, of the same name then it will store them
* in an array.
*
* All config file lines are stored as simple datatypes in the datafile.
* If you write to an existing datafile, its cprops will be overwritten.
*
*/
function CfgToDF(cfg_name, df_name, propnames)
if ( propnames.size() < 1 )
var errmsg := error;
errmsg.+errortext := "CfgToDF() Size of linenames array is < 0";
DF_OutPut(errmsg.errortext);
return errmsg;
endif
if ( lower(TypeOf(cfg_name))["string"] )
cfg_name := ReadConfigFile(cfg_name);
endif
if ( lower(TypeOf(df_name))["string"] )
df_name := DFOpenDataFile(df_name, DF_CREATE);
endif
foreach elem_name in GetConfigStringKeys(cfg_name)
var df_elem := DFFindElement(df_name, elem_name, DF_CREATE);
var elem := cfg_name[elem_name];
foreach prop_name in propnames
var entries := GetConfigStringArray(elem, prop_name);
var prop_value;
if ( entries.size() > 1 )
prop_value := array;
foreach line in GetConfigStringArray(elem, prop_name)
prop_value.Append(line);
endforeach
else
prop_value := entries[1];
endif
if ( prop_value != error )
df_elem.SetProp(prop_name, prop_value);
endif
sleepms(2);
endforeach
sleepms(2);
endforeach
return 1;
endfunction
/*
* DF_OutPut(text)
*
* Purpose
* Internal function that is used to control system logging.
*
* Parameters
* text: Text to log.
*
* Return value
* Returns 1
*
*/
function DF_OutPut(text)
if ( DF_DEBUG_MODE )
SysLog(text);
endif
return 1;
endfunction
If I understand what you want to do I think you would still have to perform a server restart even if you could create the npcdesc.cfg file from within POL. Technically speaking it is possible to unload.cfg a npcdesc file. I've done it after adding an NPC but the added NPC didn't create. I didn't get any error. It just didn't create.
So either way it seems POL needs to be restarted to load in certain parameters from the npcdesc file.
So either way it seems POL needs to be restarted to load in certain parameters from the npcdesc file.
It sounds like you simply want to make a copy of your npcdesc.cfg
Use file.em, read the npcdesc.cfg in and write what you read in to another file. No need for datafiles on this.
file.em
ReadFile()
WriteFile()
--
If you change your npcdesc.cfg you unload it with the paths
::npcdesc
:*:npcdesc
(any other packages you explicitly read into where one exists)
:pkg:npcdesc
and then you use the function in polsys.em called ReloadConfiguration() to tell the core to make use of the new template changes.
Use file.em, read the npcdesc.cfg in and write what you read in to another file. No need for datafiles on this.
file.em
ReadFile()
WriteFile()
--
If you change your npcdesc.cfg you unload it with the paths
::npcdesc
:*:npcdesc
(any other packages you explicitly read into where one exists)
:pkg:npcdesc
and then you use the function in polsys.em called ReloadConfiguration() to tell the core to make use of the new template changes.
And then?zandor wrote:You can use this include:
Code: Select all
use uo; use os; use basic; use cfgfile; use datafile; ...
It doesn't seems to help me (I haven't tryied yet), i want a datafile with "elements" as "Npctemplate"
I'm not stupid.Austin wrote:file.em
ReadFile()
WriteFile()
If i use that way the new datafile isn't seen as a datafile!!!
I get an error that tell me that elements are not called "elements" !!!
Why can't I call them "npctemplate" or "thing" or "dsfhjbr" or "sufiegy43f3" ???