forked from Jaysyn/PRC8
Updated AMS marker feats. Removed arcane & divine marker feats. Updated Dread Necromancer for epic progression. Updated weapon baseitem models. Updated new weapons for crafting & npc equip. Updated prefix. Updated release archive.
661 lines
25 KiB
HTML
661 lines
25 KiB
HTML
<html>
|
|
<head>
|
|
<title> APS/NWNX_ODBC Documentation </title>
|
|
</head>
|
|
|
|
<body style="font-family:Arial,Verdana,sans-serif;">
|
|
<h2>Avlis Persistence System</h2>
|
|
|
|
<h3>Table of Contents:</h3>
|
|
<table>
|
|
<tr>
|
|
<td> <a href="#I">I.</a></td>
|
|
<td> <a href="#I">Introduction - What does APS do?</a></td>
|
|
</tr>
|
|
<tr>
|
|
<td><a href="#II">II.</a></td>
|
|
<td><a href="#II">Installing and updating APS</a></td>
|
|
</tr>
|
|
<tr>
|
|
<td><a href="#III">III.</a></td>
|
|
<td><a href="#III">Setting up a database</a></td>
|
|
</tr>
|
|
<tr>
|
|
<td><a href="#IV">IV.</a></td>
|
|
<td><a href="#IV">Customization</a></td>
|
|
</tr>
|
|
<tr>
|
|
<td><a href="#V">V.</a></td>
|
|
<td><a href="#V">Speed comparison</a></td>
|
|
</tr>
|
|
<tr>
|
|
<td><a href="#VI">VI.</a></td>
|
|
<td><a href="#VI">Troubleshooting</a></td>
|
|
</tr>
|
|
</table>
|
|
|
|
|
|
<a name="I"></a>
|
|
<h3>I. Introduction - What does APS/NWNX ODBC2 do?</h3>
|
|
|
|
<p>APS is a set of scripts written for Neverwinter Nights that work with NWNX2 to
|
|
produce reliable persistence in a module. At the heart of the APS is
|
|
an include file that lists a number of custom made functions for governing
|
|
persistence. These functions can be used as is in your module or changed to
|
|
suit your needs.
|
|
|
|
<p>Whenever a script work with persistent data, it calls our APS functions
|
|
and the Extender pulls the query out of the memory of the NWN server. It then
|
|
passes it to the database, and writes the result of the query back into the
|
|
memory of the server. The database has been tested with MySQL, MS-SQL,
|
|
PostgresSQL, Microsoft Access, and the internal SQL database engine so far. Conceivably, any database with a
|
|
decent ODBC driver will work.
|
|
|
|
<p>We have included a demo module that illustrates how to use APS/NWNX ODBC2 and makes
|
|
creating the database tables easy, and a second module demonstrating how
|
|
persistent containers could be implemented.
|
|
|
|
<p><b>Licence</b><br> APS and NWNX2 ODBC2 are distributed unter the terms of the GNU
|
|
GENERAL PUBLIC LICENSE included in <a href="../licence.txt">licence.txt</a>.
|
|
|
|
<a name="II"></a>
|
|
<h3>II. Installing and updating APS</h3>
|
|
|
|
<h4>A. Installing the plugin</h4>
|
|
|
|
<p>Copy the file nwnx_odbc.dll to you NWN folder, and aps_demo.mod
|
|
to your NWN module folder.
|
|
|
|
<h4>B. Importing the erf</h4>
|
|
|
|
<p>In order to be able to use the APS functions, you will need to import
|
|
the aps_include file into your module.
|
|
|
|
<ol>
|
|
<li>Place the file "aps2.erf" into the C:\Neverwinternights\NWN\erf directory.
|
|
<li>In the toolset, open up the module into which you wish to install the
|
|
scripts.
|
|
<li>Under the File Menu, click Import. A window will pop up.
|
|
<li>Make sure the contents of the C:\Neverwinternights\NWN\erf directory are
|
|
showing in the window
|
|
<li>Select "aps2.erf" from the list
|
|
<li>Click Import and ignore any messages about missing resources (click Yes).
|
|
</ol>
|
|
|
|
<p>The following scripts should now be imported: aps_onload, aps_include.
|
|
|
|
<h4>C. Updating from previous versions</h4>
|
|
|
|
<ul>
|
|
<li>from ODBC v2.5 to ODBC2: Copy the new DLL into your NWN folder.
|
|
Edit the database connection parameters in your nwnx.ini file (check the
|
|
supplied example INI file what parameters can be used). Import the updated
|
|
aps_include file (from ap2.erf) into your module.
|
|
</ul>
|
|
|
|
<a name="III"></a>
|
|
<h3>Setting up a database</h3>
|
|
|
|
<p>The first choice you have to make is what database you are going to use.
|
|
We strongly suggest starting out with the internal SQL database (SQLite), which
|
|
is one of the fastest and easiest options. It also comes with a prepared datase
|
|
that is ready to go. Read the section "Configuration for the internal database" on
|
|
how to set this up.
|
|
|
|
<p>If you are using MySQL, go to the section "Configuration for MySQL
|
|
database". If you are using any other database with an ODBC driver, go
|
|
to the section "Configuration for ODBC database".
|
|
|
|
<h4>3.a. Configuration for the internal database</h4>
|
|
|
|
The internal NWNX ODBC2 database is based on SQLite v3, which is a fast SQL
|
|
compliant database that developers can package with their applications - and
|
|
that is what we did ! The main benefits of SQLite for NWN users are twofold:
|
|
|
|
<ol>
|
|
<li>It is fast.
|
|
<li>It is easy to setup (zero configuration).
|
|
</ol>
|
|
|
|
<p>Note: We recommend this type of database for single instance servers,
|
|
meaning setups where only one NWN server is accessing the database.
|
|
We recommend against using it in setups where multiple computers access
|
|
the database simultaneously.
|
|
|
|
<p>Edit the nwnx.ini file and set the source= parameter to SQLite, and
|
|
the file= parameter to the path and file where you want your database file:
|
|
|
|
<pre>
|
|
[ODBC2]
|
|
source = sqlite
|
|
file = sqlite.db
|
|
</pre>
|
|
|
|
<p>Note: Omitting the path like in the example above will put the database
|
|
file into your NWN folder. If you want it somewhere else, set the file
|
|
parameter to e.g. c:\temp\nwn.db.
|
|
|
|
<p>Hint: One of the tools for working with the internal database is
|
|
<a href="http://home.student.uu.se/frax0795/">SQLiteCC</a>. It is not
|
|
needed to follow the setup instructions in this document, but will come in
|
|
handy later.
|
|
|
|
<p>Advanced note: After opening the database file, an implicit transaction
|
|
is started automatically, since SQLite is significantly faster when access to
|
|
the database is happening inside a transaction. If you want to access the
|
|
database concurrently, or if you want to handle transactions yourself, issue
|
|
a COMMIT right after the call to SQLInit to commit the implicit transaction.
|
|
|
|
<h4>3.b. Configuration for MySQL database</h4>
|
|
|
|
<p>Below the various parameters are listed which are required in the
|
|
configuration file nwnx.ini:
|
|
|
|
<ul>
|
|
<li>Server: Either the name or IP address of the database system which you are
|
|
using. Most of the time this will be your local machine: 'localhost'.
|
|
<li>User/pwd: This is the username and password of the user which will be
|
|
used to connect to the database. For security reasons it is best to
|
|
create a special user which has only access to the nwn database.
|
|
<li>DB: The database name.
|
|
</ul>
|
|
|
|
<p>An example configuration file is displayed below. In this configuration you
|
|
tell the plugin to use the direct mysql connection to the database nwn.
|
|
This database resides on the localhost (same machine as NWN runs)
|
|
and should be connected with user 'your_user' and password 'your_pwd'.
|
|
|
|
<pre>
|
|
[ODBC2]
|
|
source = mysql
|
|
server = localhost
|
|
user = your_user
|
|
pwd = your_pwd
|
|
db = nwn
|
|
</pre>
|
|
|
|
<p>Note: If your MySQL installation is not on the same machine you are
|
|
installing this plugin too, you will need to copy the library libmysql.dll to
|
|
your NWN folder as well, or ODBC2 will complain about a missing module.
|
|
|
|
<h4>3.c. Configuration for ODBC database</h4>
|
|
|
|
<p>If you have a different database system than MySQL you will use
|
|
the ODBC connection method. In this section we will describe
|
|
the steps needed to setup your system correctly. In the description
|
|
below we asume that you are using Windows XP or a similar system.
|
|
|
|
<ul>
|
|
<li>Make sure your database system (including ODBC support) is installed
|
|
and running correctly on your machine (with a remote database system you
|
|
only need the ODBC drivers on your machine).
|
|
<li>Create an ODBC datasource: in the Control Panel select
|
|
Administrative Tools and then Data Sources (ODBC). In the System Tab
|
|
click on Add, and fill in the required fields. When finished the
|
|
datasource should appear in the list (if not, consult your database
|
|
system manual).
|
|
</ul>
|
|
|
|
Edit the nwnx.ini file and set the dsn= parameter to the name you
|
|
have just entered, e.g.:
|
|
|
|
<pre>
|
|
[ODBC2]
|
|
source = odbc
|
|
dsn = nwn
|
|
</pre>
|
|
|
|
<h4>3.c. Creating the database tables</h4>
|
|
|
|
<p>Note: As there is an almost unlimited amount of different databases
|
|
out there, we can not give detailed instructions for all of them. If you want
|
|
to use a database server like MSSQL or PostgresSQL, try to follow the steps
|
|
described below accordingly. If you are using the internal database, all tables have already been
|
|
created for you (in the file sqlite.db).
|
|
|
|
<p>Make sure your database is up and running and that you have a
|
|
database that is accessible to the ODBC2 plugin. In order to store data in it,
|
|
you have to create some tables in the database. The included module
|
|
"aps_demo.mod" makes this easy for the internal database and MySQL.
|
|
By default, it creates tables for the internal database. If you want to use
|
|
MySQL instead, open the module with the toolset and edit the scripts
|
|
"demo_createtable" and "demo_obj_create" accordingly.
|
|
|
|
<p>Next connect to your server with the Neverwinter Nights client.
|
|
On the left side, you will see several different signs in front of you:
|
|
|
|
<ul>
|
|
<li>Create table: Issues a database command that creates a table
|
|
in the database
|
|
<li>Store variable in database: Tries to save a test variable named
|
|
"demoName" with the value "testValue" in the database
|
|
<li>Load variable from database: Tries to retrieve the variable
|
|
"demoName" from the database and prints the results in the
|
|
server message window.
|
|
</ul>
|
|
|
|
<p>Now click every sign once, starting with the one on the
|
|
left (Create Tables).
|
|
|
|
<p>If the last sign sends you the message "Retrieved variable from
|
|
database: testValue" your setup is ok and you're ready to start using APS.
|
|
Note: This is the most basic setup. We encourage you to use more
|
|
sophisticated databases and data structures if you feel confident
|
|
to do so (see below).
|
|
|
|
<p> On the right side, you will see several different signs that do almost
|
|
the same as the other signs, but they are dealing with object instead
|
|
of strings storage.
|
|
|
|
<p> If the variable is not retrieved correctly, check out the log file
|
|
nwnx_odbc.txt for errors. Also check your database if the table really
|
|
has been created. The SQL statement that is executed by default is suitable for MySQL. If you use a
|
|
different database server, you should adjust that statement accordingly:
|
|
|
|
<p>Create a table "pwdata" with the following fields
|
|
player, tag, name, val, expire, last. Here is an example for MySQL
|
|
(taken from aps_demo.mod, script demo_createtable):
|
|
|
|
<pre>
|
|
SQLExecDirect("CREATE TABLE pwdata (" +
|
|
"player varchar(64) default NULL," +
|
|
"tag varchar(64) default NULL," +
|
|
"name varchar(64) default NULL," +
|
|
"val text," +
|
|
"expire int(11) default NULL," +
|
|
"last timestamp(14) NOT NULL," +
|
|
"KEY idx (player,tag,name)" +
|
|
")" );
|
|
|
|
</pre>
|
|
|
|
<h4>E. Using the persistence functions in your module</h4>
|
|
|
|
<ol>
|
|
<li>After installing according to the instructions above, go to Module
|
|
Properties under the Edit menu.
|
|
<li> Select aps_onload for your module OnModuleLoad event.<br>
|
|
OR<br>
|
|
Open aps_onload in the script editor and paste the contents of it into your
|
|
pre-existing module's OnModuleLoad script. We only recommend doing this if you
|
|
are familiar with NWScript.
|
|
</ol>
|
|
|
|
The functions below are now implemented. Here is a lexicon containing
|
|
information on their purpose and use:
|
|
|
|
<p><b>void SQLInit()</b>
|
|
<p>Setup placeholders for ODBC requests and responses. This functions reserves memory APS and NWNX
|
|
use for communication. Call this function <b>once</b> in the module load event.
|
|
|
|
<p><b>SetPersistentString(object oObject, string sVarName, string sValue,
|
|
int iExpiration=0, string sTable="pwdata")</b>
|
|
|
|
<p>This sets a persistent string on an object. The object can be
|
|
any valid object in the game. The command works the same way the usual
|
|
SetLocalString function works, except you can optionally add a little more
|
|
information:
|
|
|
|
<ul>
|
|
<li>object oObject - The object which you wish to set the persistent variable
|
|
upon.
|
|
<li>string sVarName - The name of the persistent variable. Ex: "Quest Flag 1"
|
|
or "QuestCompleted_True_False"
|
|
<li>string sValue - The string you want to store.
|
|
<li>int Expiration - (optional) The number of days after which the variable should
|
|
expire, i.e. be deleted from the database. If you don't specify this parameter
|
|
or pass 0 here, the variable will never be purged from the database.
|
|
<li>string sTable - (optional) You can specify in which database table the value
|
|
should be stored. This parameter defaults to "pwdata".
|
|
</ul>
|
|
|
|
<p><b>SetPersistentInt(object oObject, string sVarName, int iValue,
|
|
int iExpiration=0, string sTable="pwdata")</b>
|
|
|
|
<p>This sets a persistent integer value on an object. The object can be
|
|
any valid object in the game. The command works the same way the usual
|
|
SetLocalInt function works, except you can optionally add a little more
|
|
information:
|
|
|
|
<ul>
|
|
<li>object oObject - The object which you wish to set the persistent variable
|
|
upon.
|
|
<li>string sVarName - The name of the persistent variable. Ex: "Quest Flag 1"
|
|
or "QuestCompleted_True_False"
|
|
<li>int iValue - The integer value of the variable. 1, 2, 3... etc.
|
|
<li>int Expiration - (optional) The number of days after which the variable should
|
|
expire, i.e. be deleted from the database. If you don't specify this parameter
|
|
or pass 0 here, the variable will never be purged from the database.
|
|
<li>string sTable - (optional) You can specify in which database table the value
|
|
should be stored. This parameter defaults to "pwdata".
|
|
</ul>
|
|
|
|
<p><b>SetPersistentFloat(object oObject, string sVarName, float fValue,
|
|
int iExpiration=0, string sTable="pwdata")</b>
|
|
|
|
<p>This sets a persistent float value on an object. The object can be
|
|
any valid object in the game. The command works the same way the usual
|
|
|
|
SetLocalFloat function works, except you can optionally add a little more
|
|
information:
|
|
|
|
<ul>
|
|
<li>object oObject - The object which you wish to set the persistent variable
|
|
upon.
|
|
<li>string sVarName - The name of the persistent variable. Ex: "Quest Flag 1"
|
|
or "QuestCompleted_True_False"
|
|
<li>float fValue - The float value of the variable. 1.6, 2.542, 3.0989... etc.
|
|
<li>int Expiration - (optional) The number of days after which the variable should
|
|
expire, i.e. be deleted from the database. If you don't specify this parameter
|
|
or pass 0 here, the variable will never be purged from the database.
|
|
<li>string sTable - (optional) You can specify in which database table the value
|
|
should be stored. This parameter defaults to "pwdata".
|
|
</ul>
|
|
|
|
<p><b>SetPersistentLocation(object oObject, string sVarName, location lLocation,
|
|
int iExpiration=0, string sTable="pwdata")</b>
|
|
|
|
<p>This sets a persistent location on an object. The object can be
|
|
any valid object in the game. The command works the same way the usual
|
|
SetLocalLocation function works, except you can optionally add a little more
|
|
information:
|
|
|
|
<ul>
|
|
<li>object oObject - The object which you wish to set the persistent variable
|
|
upon.
|
|
<li>string sVarName - The name of the persistent variable. Ex: "Quest Flag 1"
|
|
or "QuestCompleted_True_False"
|
|
<li>location lLocation - The location you want to store.
|
|
<li>int Expiration - (optional) The number of days after which the variable should
|
|
expire, i.e. be deleted from the database. If you don't specify this parameter
|
|
or pass 0 here, the variable will never be purged from the database.
|
|
<li>string sTable - (optional) You can specify in which database table the value
|
|
should be stored. This parameter defaults to "pwdata".
|
|
</ul>
|
|
|
|
<p><b>SetPersistentVector(object oObject, string sVarName, vector vVector,
|
|
int iExpiration=0, string sTable="pwdata")</b>
|
|
|
|
<p>This sets a persistent vector on an object. The object can be
|
|
any valid object in the game. The command works the same way the usual
|
|
Set local variable functions work, except you can optionally add a little more
|
|
information:
|
|
|
|
<ul>
|
|
<li>object oObject - The object which you wish to set the persistent variable
|
|
upon.
|
|
<li>string sVarName - The name of the persistent variable. Ex: "Quest Flag 1"
|
|
or "QuestCompleted_True_False"
|
|
<li>vector vVector - The vector you want to store.
|
|
<li>int Expiration - (optional) The number of days after which the variable should
|
|
expire, i.e. be deleted from the database. If you don't specify this parameter
|
|
or pass 0 here, the variable will never be purged from the database.
|
|
<li>string sTable - (optional) You can specify in which database table the value
|
|
should be stored. This parameter defaults to "pwdata".
|
|
</ul>
|
|
|
|
<p><b>GetPersistentString(object oObject, string sVarName, string sTable="pwdata")</b>
|
|
|
|
<p>This function works in the same manner as GetLocalString. It gets the
|
|
persistent string from object oObject.
|
|
|
|
<ul>
|
|
<li>object oObject - This is the object from which you are retrieving the
|
|
value of the variable.
|
|
<li>string sVarName - This is the name of the variable that will be retrieved
|
|
off of oObject. Ex: "Quest Flag 1"
|
|
<li>string sTable - (optional) You can specify in which database table the value
|
|
can be found. This parameter defaults to "pwdata".
|
|
</ul>
|
|
|
|
<p><b>GetPersistentInt(object oObject, string sVarName, string sTable="pwdata")</b>
|
|
|
|
<p>This function works in the same manner as GetLocalInt. It gets the
|
|
persistent integer value from object oObject.
|
|
|
|
<ul>
|
|
<li>object oObject - This is the object from which you are retrieving the
|
|
value of the variable.
|
|
|
|
<li>string sVarName - This is the name of the variable that will be retrieved
|
|
off of oObject. Ex: "Quest Flag 1"
|
|
<li>string sTable - (optional) You can specify in which database table the value
|
|
can be found. This parameter defaults to "pwdata".
|
|
</ul>
|
|
|
|
<p><b>GetPersistentFloat(object oObject, string sVarName, string sTable="pwdata")</b>
|
|
|
|
<p>This function works in the same manner as GetLocalFloat. It gets the
|
|
persistent float value from object oObject.
|
|
|
|
<ul>
|
|
<li>object oObject - This is the object from which you are retrieving the
|
|
value of the variable.
|
|
<li>string sVarName - This is the name of the variable that will be retrieved
|
|
off of oObject. Ex: "Quest Flag 1"
|
|
<li>string sTable - (optional) You can specify in which database table the value
|
|
can be found. This parameter defaults to "pwdata".
|
|
</ul>
|
|
|
|
<p><b>GetPersistentLocation(object oObject, string sVarName, string sTable="pwdata")</b>
|
|
|
|
<p>This function works in the same manner as GetLocalLocation. It gets the
|
|
persistent location value from object oObject.
|
|
|
|
<ul>
|
|
<li>object oObject - This is the object from which you are retrieving the
|
|
value of the variable.
|
|
<li>string sVarName - This is the name of the variable that will be retrieved
|
|
off of oObject. Ex: "Quest Flag 1"
|
|
<li>string sTable - (optional) You can specify in which database table the value
|
|
can be found. This parameter defaults to "pwdata".
|
|
</ul>
|
|
|
|
<p><b>GetPersistentVector(object oObject, string sVarName, string sTable="pwdata")</b>
|
|
|
|
<p>This function works in the same manner as the other get local variable functions. It gets the
|
|
persistent vector value from object oObject.
|
|
|
|
<ul>
|
|
<li>object oObject - This is the object from which you are retrieving the
|
|
value of the variable.
|
|
<li>string sVarName - This is the name of the variable that will be retrieved
|
|
off of oObject. Ex: "Quest Flag 1"
|
|
<li>string sTable - (optional) You can specify in which database table the value
|
|
can be found. This parameter defaults to "pwdata".
|
|
</ul>
|
|
|
|
<p><b>void DeletePersistentVariable(object oObject, string sVarName, string sTable="pwdata")</b>
|
|
|
|
<p>This function deletes a variable from the database.
|
|
|
|
<ul>
|
|
<li>object oObject - This is the object on which the variable has been stored.
|
|
<li>string sVarName - This is the name of the variable that will be deleted.
|
|
<li>string sTable - (optional) You can specify in which database table the value
|
|
can be found. This parameter defaults to "pwdata".
|
|
</ul>
|
|
|
|
<p><b>void SQLExecDirect(string sSQL)</b>
|
|
<p> Executes a SQL statement. If the statement returns a result set, you can read the data
|
|
with the next two functions.
|
|
|
|
<p><b>int SQLFetch()</b>
|
|
<p> Position cursor on next row of the resultset. Call this function before using SQLGetData().<br>
|
|
Returns
|
|
<ul>
|
|
<li>SQL_SUCCESS if there is a row
|
|
<li>SQL_ERROR if there are no more rows
|
|
</ul>
|
|
|
|
<p><b>int SQLFirstRow() (*deprecated*)</b>
|
|
<p> Function is deprecated but still there for backward compability. Simply calls SQLFetch().
|
|
|
|
<p><b>int SQLNextRow() (*deprecated*)</b>
|
|
<p> Function is deprecated but still there for backward compability. Simply calls SQLFetch().
|
|
|
|
<p><b>string SQLGetData(int iCol)</b>
|
|
<p> Return value of column iCol in the current row of result set sResultSetName.
|
|
|
|
<p><b>Comments</b>
|
|
|
|
<ul>
|
|
<li>Make sure you include aps_include in every script where you want to use these functions,
|
|
i.e. add the line
|
|
<pre>
|
|
#include "aps_include"
|
|
</pre>
|
|
at the top of your script.
|
|
</ul>
|
|
|
|
<a name="IV"></a>
|
|
<h3>IV. Customization</h3>
|
|
|
|
<p>The APS is merely a set of custom functions that were originally used for the Avlis
|
|
persistent world. The names of the functions and their parameters can be set to whatever
|
|
is convenient for your module. Below is a hypothetical example of how customization can be done.
|
|
|
|
<p>The "PowerG I33t" persistent world maintains their persistence with the Joe Bloe Persistence
|
|
system (JBPS). In that system, a persistent string is set with the following JBPS function:
|
|
|
|
<p>SetStickySring(string sVariableName, string sVariableValue, object oTarget)
|
|
|
|
<p>All 5000 scripts in PowerG's elite world are written with the SetStickyString function, and they
|
|
wish to retrofit their world to use NWNX. They would follow these steps:
|
|
|
|
<ol>
|
|
<li>Open up the file aps_include in the script editor.
|
|
<li>Change the name of the APS function called SetPersistentString to SetStickyString.
|
|
<li>Rearrange the parameters of:
|
|
|
|
<p>SetPersistentString(object oObject, string sVarName, string sVarValue, int iExpiration, string sTable = "pwdata")<br>
|
|
to:<br>
|
|
SetStickyString(string VarName, string VarValue, object oObject, int iExpiration = 0, string sTable = "pwdata")<br>
|
|
|
|
<li>Build the module, i.e. recompile all scripts.
|
|
|
|
</ol>
|
|
|
|
<p>Once the module is restarted, all of PowerG I33t's old persistent string scripts should be running the
|
|
new persistence system. All it took was changing one script.
|
|
|
|
<p>The above example is a simplified one, and the rest of the functions in the JBPS would need to be changed
|
|
in the same manner. In cases where the function parameters were completely not equivalent to those used
|
|
by the APS, they may have to be changed throughout every script in the module. Many but not all of the
|
|
persistence systems out there should be convertible by the above method. We encourage further modification
|
|
of aps_include to tailor the variable handling to your needs.
|
|
|
|
<p>For persistence systems that use tokens, conversion will not be as easy. In these systems, token items
|
|
are used to represent information on a player character. These tokens are not lost because they are
|
|
actually in the inventory of the character. Because these systems work with tokens and not actual variables
|
|
it will be hard to convert them into a database format. The module will most likely have to be completely
|
|
re-fitted.
|
|
|
|
<p>On possible idea to do this scriptomatically would be to write a module OnEnter script that strips the
|
|
character of their tokens and issues SetPersistent variable commands into the database before destroying
|
|
them. That would preserve the information that is there, but handling the actual scripts throughout the
|
|
module will have to be done separately.
|
|
|
|
<p>Alternatively, you can have a look at the GetPersistentString() function in
|
|
"aps_include". There are some comments in this functions that should give you
|
|
ideas on how to convert persistent data from your current system to APS.
|
|
|
|
<a name="V"></a>
|
|
<h3>V. Speed comparison </h3>
|
|
|
|
<p>To give you an idea what to expect from the various database options, we
|
|
conducted a small test involving 500 writes and reads. Note that this test is
|
|
very artificial, since many aspects like table fragmentation, concurrent access,
|
|
database size, and more realistic queries are not factored in. All tests were
|
|
done on a Athlon 64 3200+ with database server, NWServer, and NWClient
|
|
running local (NWClient with reduced process priority).
|
|
|
|
<p>Writes were done with the following code:
|
|
<pre>
|
|
for (i = 0; i < 500; i++)
|
|
{
|
|
SQLExecDirect("INSERT INTO pwdata (player, tag, name,val) values " +
|
|
"('~', '~', 'iter_" + IntToString(i) + "', 'value')");
|
|
}
|
|
</pre>
|
|
|
|
<p>Reads were done with the following code:
|
|
<pre>
|
|
SQLExecDirect("SELECT * from pwdata");
|
|
while (SQLFetch() == SQL_SUCCESS) {}
|
|
</pre>
|
|
|
|
<p>Bioware DB reads and write were done with the following code:
|
|
<pre>
|
|
for (i = 0; i < 500; i++)
|
|
{
|
|
SetCampaignString("test", "iter_" + IntToString(i), "value");
|
|
-- respecively --
|
|
s = GetCampaignString("test", "iter_" + IntToString(i));
|
|
}
|
|
</pre>
|
|
|
|
<p>Results:
|
|
<table border="1" width="300" style="margin-left:2em;">
|
|
<tr>
|
|
<td>Database</td>
|
|
<td>Write</td>
|
|
<td>Read</td>
|
|
</tr>
|
|
<tr>
|
|
<td>SQLite (1)</td>
|
|
<td>30 ms</td>
|
|
<td>20 ms</td>
|
|
</tr>
|
|
<tr>
|
|
<td>SQLite (2)</td>
|
|
<td>36 ms</td>
|
|
<td>20 ms</td>
|
|
</tr>
|
|
<tr>
|
|
<td>SQLite (3)</td>
|
|
<td>2800 ms</td>
|
|
<td>20 ms</td>
|
|
</tr>
|
|
<tr>
|
|
<td>MySQL via ODBC</td>
|
|
<td>71 ms</td>
|
|
<td>38 ms</td>
|
|
</tr>
|
|
<tr>
|
|
<td>MySQL direct</td>
|
|
<td>68 ms</td>
|
|
<td>22 ms</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Bioware DB (4)</td>
|
|
<td>856 ms</td>
|
|
<td>10 ms</td>
|
|
</tr>
|
|
<table>
|
|
|
|
<p>Comments:
|
|
<ul>
|
|
<li>SQLITE (1): Using a transaction. No commit after the for loop.
|
|
<li>SQLITE (2): Using a transaction. Commit after the for loop.
|
|
<li>SQLITE (3): Not using a transaction. Terribly slow ! Note that
|
|
NWNX ODBC2 starts an implicit transaction automatically. If you want
|
|
to handle transactions yourself, issue a COMMIT right after SQLInit()
|
|
to end the implicit transaction.
|
|
<li>Bioware DB (4): This comparison is a bit unfair, since the call to the
|
|
Bioware database is significantly simpler and less flexible than its ODBC2
|
|
counterpart. Real world examples utilizing e.g. SQL resultsets would probably
|
|
favor ODBC2.
|
|
</ul>
|
|
|
|
<a name="VI"></a>
|
|
<h3>VI. Troubleshooting </h3>
|
|
|
|
<p> Starting out with NWNX ODBC2 can be a bit daunting at first, especially
|
|
if you are on your own. We highly encourage you to visit us at
|
|
<a href="http://www.nwnx.org">www.nwnx.org</a> to ask question and get
|
|
help with setting this system up.
|
|
|
|
</body>
|
|
</html>
|