748 lines
30 KiB
Plaintext
748 lines
30 KiB
Plaintext
//void main(){}
|
||
|
||
//::///////////////////////////////////////////////
|
||
//:: Natural Bioware Database Extension v1.0
|
||
//:: nbde_inc
|
||
//:: Copyright (c) 2001 Bioware Corp.
|
||
//:://////////////////////////////////////////////
|
||
/*
|
||
|
||
*/
|
||
//:://////////////////////////////////////////////
|
||
//:: Created By: Knat
|
||
//:: Created On: 8/2004
|
||
//:://////////////////////////////////////////////
|
||
/*
|
||
|
||
Natural Bioware Database Extension v1.0
|
||
"Andale, Andale! EEEE-ha....!"
|
||
|
||
-----------------------------------------------------------------------------
|
||
--- What is NBDE ?
|
||
-----------------------------------------------------------------------------
|
||
|
||
NBDE is basically a wrapper for the standard bioware database system,
|
||
eliminating most of its restrictions. But even more important, it significantly
|
||
boosts both reading and writing speed.
|
||
|
||
It will make your db scripts more secure and always keeps your database files
|
||
in the best possible shape. It furthermore reduces the amount of overhead in
|
||
your database and keeps it as slim as possible.
|
||
|
||
there is no need to periodically use a pack utility, which further
|
||
reduces administrative tasks...
|
||
|
||
and this all gets achieved with the use of this simple script. I recommend any
|
||
scripter to check this out if he plans to use biowares onboard database
|
||
functionality. It should also be very easy to convert already existing scripts.
|
||
|
||
-----------------------------------------------------------------------------
|
||
--- Installation
|
||
-----------------------------------------------------------------------------
|
||
|
||
Simply import nbde.erf and you are done.
|
||
|
||
It includes the following stuff:
|
||
|
||
Scripts:
|
||
|
||
name: nbde_inc
|
||
main include script...
|
||
|
||
Areas:
|
||
|
||
name: _NBDE
|
||
special area. this is a 2x2 microset area holding the database vault container.
|
||
you can delete this area and move the container to another place if you want.
|
||
|
||
Items:
|
||
|
||
Custom > Special > Custom 4
|
||
name: Database
|
||
special database item with the resref "nbde_database"
|
||
don't touch this item...
|
||
|
||
-----------------------------------------------------------------------------
|
||
--- Eliminated Restrictions ?
|
||
-----------------------------------------------------------------------------
|
||
|
||
Biowares database system mimics the interface of Local Variables.
|
||
Instead of SetLocalInt() you use SetCampaignInt(), GetLocalInt() turns into
|
||
GetCampaignInt(). This makes it very easy to use, even for novice scripters.
|
||
But the normal bioware database does not consequently implement this approach.
|
||
Several stumbling blocks, slight differences to normal Set-/GetLocal functions,
|
||
may lead to severe functional problems and hard to track bugs if you try to
|
||
achieve a bit more complex goals...
|
||
|
||
>>> 32-Char sVarName Limitation:
|
||
--------------------------------
|
||
|
||
the sVarName parameter in the original functions only accepts strings with a
|
||
maximum length of 32 chars. it will simply cut the string if it exceeds this
|
||
limit...
|
||
|
||
example:
|
||
|
||
SetCampaignInt("MYDB", "PREFIX" + GetTag(oArea), 100);
|
||
|
||
The second parameter is the sVarName one, with the 32 char limit. The above
|
||
statement is a bit risky, because GetTag(oArea) could return a string with a
|
||
maximum length of 32. "PREFIX" has a length of 6 chars, so any area with a
|
||
tag of length >26 could lead to unintended sVarNames.
|
||
|
||
Same for this example:
|
||
|
||
SetCampaignInt("MYDB", GetName(oPC) + GetPCPlayerName(oPC), 100);
|
||
|
||
same problem. GetName() alone may return a string with a length >32, which
|
||
could again lead to a problematic sVarName.
|
||
|
||
NBDE completely eliminates the 32-char sVarName limitation and enables the
|
||
scripter to use the full scope of dynamically concatenated sVarNames,
|
||
without the need of hashing systems or other workarounds, which generally
|
||
consume a bit of extra cpu time...
|
||
|
||
>>> UNIQUE sVarName Limitation:
|
||
-------------------------------
|
||
|
||
the sVarName parameter in the original functions MUST be unique across the
|
||
entire database, regardless of the variable type.
|
||
|
||
example:
|
||
|
||
SetCampaignInt("MYDB", "TEST", 10);
|
||
SetCampaignString("MYDB", "TEST", "ABCD");
|
||
|
||
the second line will OVERWRITE the former integer variable "TEST" with a string.
|
||
This means a GetCampaignInt("MYDB", "TEST") returns 0
|
||
|
||
using NBDE eliminates this limitation.
|
||
It works now similar to LocalVariables (the intended goal)
|
||
|
||
NBDE conversion of the above example:
|
||
|
||
NBDE_SetCampaignInt("MYDB", "TEST", 10);
|
||
NBDE_SetCampaignString("MYDB", "TEST", "ABCD");
|
||
|
||
second line will not overwrite the integer variable
|
||
|
||
NBDE_GetCampaignInt("MYDB", "TEST") returns the correct 10
|
||
NBDE_GetCampaignString("MYDB", "TEST") returns "ABCD"
|
||
|
||
The original function set contains only one delete command, called
|
||
DeleteCampaignVariable(), because of the unique nature of sVarNames.
|
||
|
||
NBDE contains one delete command for each variable type, to account for the
|
||
possible non uniqueness:
|
||
|
||
NBDE_DeleteCampaignInt()
|
||
NBDE_DeleteCampaignFloat()
|
||
NBDE_DeleteCampaignString()
|
||
NBDE_DeleteCampaignVector()
|
||
NBDE_DeleteCampaignLocation()
|
||
|
||
this again now works similar to the LocalVariables interface, which also
|
||
gives you a delete command for each variable type:
|
||
|
||
aka DeleteLoaclInt(), DeleteLocalFloat(), DeleteLocalString(),
|
||
DeleteLocalVector(), DeleteLocalLocation()
|
||
|
||
>>> Broken Locations:
|
||
---------------------
|
||
|
||
the original SetCampaignLocation/GetCampaignLocation functions are not very
|
||
reliable, because they are using the areas object-id for reference, which
|
||
is a runtime generated ID. stored locations in the database can get invalid
|
||
if you change the area layout in the toolset (e.g. deleting old areas, etc.)
|
||
|
||
nbde location functions are 100% reliable, as long as you use unique TAGs for
|
||
your areas. I repeat, you need to use UNIQUE TAGS for your areas...
|
||
|
||
-----------------------------------------------------------------------------
|
||
--- No need to pack the database
|
||
-----------------------------------------------------------------------------
|
||
|
||
NWN's database files grow very large, very fast, because deleted entries get
|
||
only "flagged" as deleted. but they still reside in the dabase file physically.
|
||
|
||
to stop this evergrowing database, you usually call an external "pack"
|
||
utility which reorganizes the database files (deletion of flagged entries,
|
||
index re-ordering, etc.)
|
||
|
||
unfortunately, the only working pack utility is the one you find in the
|
||
/utils directory, called DataPack.exe . But some people reported problems
|
||
on large database files... (i never had problems with this tool, though)
|
||
|
||
the good news is, you don't need to touch this utility ever, while using
|
||
this extension. NBDE will automatically keep all your database files as
|
||
compact/small as possible.
|
||
|
||
no external maintenance needed...
|
||
|
||
NBDE_Delete commands immediately shrink your database in size (physically
|
||
deleted records) after a flushing command (read more about that in a minute).
|
||
|
||
attention:
|
||
there is a known problem in the linux version:
|
||
|
||
The DestroyCampaignDatabase command doesnt always work in linux. i think
|
||
this relates to the different file systems used.
|
||
|
||
you should be ok using the following rules for your database
|
||
names (sCampaignName parameter):
|
||
|
||
- max length 16 chars
|
||
- only use alphanumeric chars and underscore
|
||
- NO space
|
||
|
||
|
||
-----------------------------------------------------------------------------
|
||
--- Usage
|
||
-----------------------------------------------------------------------------
|
||
|
||
first, include nbde_inc to all scripts using this extension:
|
||
|
||
#include "nbde_inc"
|
||
|
||
You basically use it the same way you would use the original
|
||
database. just add the NBDE_ prefix infront of the function.
|
||
|
||
original example:
|
||
|
||
int n = GetCampaignInt("MYDB", "MYVAR");
|
||
|
||
nbde conversion:
|
||
|
||
#include "nbde_inc"
|
||
|
||
int n = NBDE_GetCampaignInt("MYDB", "MYVAR");
|
||
|
||
Important differences:
|
||
|
||
Database Flushing:
|
||
------------------
|
||
|
||
writing to the database will not issue a physical write directly.
|
||
You need to "Flush" a database in order to physically write the contents of
|
||
a complete database to your HD. this sounds slow, but its not, because of
|
||
the large overhead of standard SetCampaign calls...
|
||
Writing out a single integer via SetCampaignInt takes roughly
|
||
100ms (0.1 seconds), writing out an object with 1000 integers via
|
||
SetCampaignObject takes roughly 150ms. that's the whole
|
||
magic behind the system. it basically just consolidates your writes..
|
||
|
||
original example:
|
||
|
||
SetCampaignInt("MYDB", "MYVAR1", 10);
|
||
SetCampaignInt("MYDB", "MYVAR2", 20);
|
||
SetCampaignInt("MYDB", "MYVAR3", 30);
|
||
SetCampaignInt("MYDB", "MYVAR4", 40);
|
||
SetCampaignInt("MYDB", "MYVAR5", 50);
|
||
|
||
nbde conversion:
|
||
|
||
NBDE_SetCampaignInt("MYDB", "MYVAR1", 10);
|
||
NBDE_SetCampaignInt("MYDB", "MYVAR2", 20);
|
||
NBDE_SetCampaignInt("MYDB", "MYVAR3", 30);
|
||
NBDE_SetCampaignInt("MYDB", "MYVAR4", 40);
|
||
NBDE_SetCampaignInt("MYDB", "MYVAR5", 50);
|
||
NBDE_FlushCampaignDatabase("MYDB");
|
||
|
||
the original example takes roughly half a second (500ms),
|
||
the converted example only 100ms.
|
||
|
||
you can gain a lot of speed and do things impossible with the original
|
||
database using the right flushing scheme. you can flush critical data asap
|
||
but you can get away flushing not so critical stuff only once every few
|
||
minutes, or during onClientLeave, or once an Area is out of players, and so on...
|
||
|
||
keep in mind: you can loose data if the server crashes before
|
||
you flushed your database.
|
||
|
||
delete function:
|
||
----------------
|
||
|
||
the original version only got one delete function, DeleteCampaignVariable.
|
||
That's because of the unique nature of sVarNames...
|
||
NBDE eliminates this restriction and therefore exposes one delete
|
||
function for each data-type.
|
||
|
||
original example:
|
||
|
||
DeleteCampaignVariable("MYDB", "MYVAR");
|
||
|
||
you need to know the datatype of "MYVAR" in order to correctly convert this
|
||
line to NBDE. lets assume it's an integer...
|
||
|
||
nbde conversion:
|
||
|
||
NBDE_DeleteCampaignInt("MYDB", "MYVAR");
|
||
|
||
|
||
Unloading a Database:
|
||
---------------------
|
||
|
||
nbde databases are kept in memory. NBDE_UnloadCampaignDatabase() unloads
|
||
the database with the name sCampaignName from memory.
|
||
|
||
useful to unload databases you don't need often. unloading/reloading is quite
|
||
fast, so don't hesitate to use this regulary...
|
||
|
||
|
||
*/
|
||
|
||
// database item name, used as sVarName parameter in Store-/RetrieveCampaignObject
|
||
const string NBDE_DATABASE_ITEM_VARNAME = "+++_DATABASE_ITEM_+++";
|
||
|
||
// database item resref, needed for auto-creation
|
||
const string NBDE_DATABASE_ITEM_RESREF = "nbde_database";
|
||
|
||
// database index prefix
|
||
// used to index a database via Get/SetLocalObject
|
||
const string NBDE_INDEX_PREFIX = "NBDE_DATABASE_";
|
||
|
||
// database vault tag
|
||
// this vault is usually a container
|
||
const string NBDE_VAULT_TAG = "NBDE_VAULT";
|
||
|
||
// prefixes used to store locations/vectors as strings
|
||
// this should eliminate collisions with normal strings
|
||
const string NBDE_LOC_PREFIX = "<22>ƥ";
|
||
const string NBDE_VEC_PREFIX = "<22><><EFBFBD>";
|
||
|
||
// This stores an int out to the specified campaign database
|
||
// The database name IS case sensitive and it must be the same for both set and get functions.
|
||
// If you want a variable to pertain to a specific player in the game, provide a player object.
|
||
//
|
||
// Improvements to original bioware function:
|
||
// Vastly improved writing speed...
|
||
// There is no limit on the length of sVarname (original function is limited to 32 chars)
|
||
// sVarname must NOT be unique. you can use the same sVarname with a different data-type
|
||
void NBDE_SetCampaignInt(string sCampaignName, string sVarname, int nInt, object oPlayer = OBJECT_INVALID);
|
||
|
||
// This stores a float out to the specified campaign database
|
||
// The database name IS case sensitive and it must be the same for both set and get functions.
|
||
// If you want a variable to pertain to a specific player in the game, provide a player object.
|
||
//
|
||
// Improvements to original bioware function:
|
||
// Vastly improved writing speed...
|
||
// There is no limit on the length of sVarname (original function is limited to 32 chars)
|
||
// sVarname must NOT be unique. you can use the same sVarname with a different data-type
|
||
void NBDE_SetCampaignFloat(string sCampaignName, string sVarname, float flFloat, object oPlayer = OBJECT_INVALID);
|
||
|
||
// This stores a string out to the specified campaign database
|
||
// The database name IS case sensitive and it must be the same for both set and get functions.
|
||
// If you want a variable to pertain to a specific player in the game, provide a player object.
|
||
//
|
||
// Improvements to original bioware function:
|
||
// Vastly improved writing speed...
|
||
// There is no limit on the length of sVarname (original function is limited to 32 chars)
|
||
// sVarname must NOT be unique. you can use the same sVarname with a different data-type
|
||
void NBDE_SetCampaignString(string sCampaignName, string sVarname, string sString, object oPlayer = OBJECT_INVALID);
|
||
|
||
// This stores a location out to the specified campaign database
|
||
// The database name IS case sensitive and it must be the same for both set and get functions.
|
||
// If you want a variable to pertain to a specific player in the game, provide a player object.
|
||
//
|
||
// Improvements to original bioware function:
|
||
// Vastly improved writing speed...
|
||
// There is no limit on the length of sVarname (original function is limited to 32 chars)
|
||
// sVarname must NOT be unique. you can use the same sVarname with a different data-type
|
||
//
|
||
// Original function is not very reliable, because it is using the areas object-id, which is
|
||
// a runtime generated ID. Stored locations may turn invalid in case you change the area layout in the toolset.
|
||
// (e.g. deleting old areas)
|
||
//
|
||
// This function is 100% reliable, as long as you use unique TAGs for your areas
|
||
void NBDE_SetCampaignLocation(string sCampaignName, string sVarname, location locLocation, object oPlayer = OBJECT_SELF);
|
||
|
||
// This stores a vector out to the specified campaign database
|
||
// The database name IS case sensitive and it must be the same for both set and get functions.
|
||
// If you want a variable to pertain to a specific player in the game, provide a player object.
|
||
//
|
||
// Improvements to original bioware function:
|
||
// Vastly improved writing speed...
|
||
// There is no limit on the length of sVarname (original function is limited to 32 chars)
|
||
// sVarname must NOT be unique. you can use the same sVarname with a different data-type
|
||
void NBDE_SetCampaignVector(string sCampaignName, string sVarname, vector vVector, object oPlayer = OBJECT_SELF);
|
||
|
||
// This will read an int from the specified campaign database
|
||
// The database name IS case sensitive and it must be the same for both set and get functions.
|
||
// If you want a variable to pertain to a specific player in the game, provide a player object.
|
||
//
|
||
// Improvements to original bioware function:
|
||
// Improved reading speed...
|
||
// There is no limit on the length of sVarname (original function is limited to 32 chars)
|
||
// sVarname must NOT be unique. you can use the same sVarname with a different data-type
|
||
int NBDE_GetCampaignInt(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID);
|
||
|
||
// This will read a float from the specified campaign database
|
||
// The database name IS case sensitive and it must be the same for both set and get functions.
|
||
// If you want a variable to pertain to a specific player in the game, provide a player object.
|
||
//
|
||
// Improvements to original bioware function:
|
||
// Improved reading speed...
|
||
// There is no limit on the length of sVarname (original function is limited to 32 chars)
|
||
// sVarname must NOT be unique. you can use the same sVarname with a different data-type
|
||
float NBDE_GetCampaignFloat(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID);
|
||
|
||
// This will read a string from the specified campaign database
|
||
// The database name IS case sensitive and it must be the same for both set and get functions.
|
||
// If you want a variable to pertain to a specific player in the game, provide a player object.
|
||
//
|
||
// Improvements to original bioware function:
|
||
// Improved reading speed...
|
||
// There is no limit on the length of sVarname (original function is limited to 32 chars)
|
||
// sVarname must NOT be unique. you can use the same sVarname with a different data-type
|
||
string NBDE_GetCampaignString(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID);
|
||
|
||
// This will read a location from the specified campaign database
|
||
// The database name IS case sensitive and it must be the same for both set and get functions.
|
||
// If you want a variable to pertain to a specific player in the game, provide a player object.
|
||
//
|
||
// Improvements to original bioware function:
|
||
// Improved reading speed...
|
||
// There is no limit on the length of sVarname (original function is limited to 32 chars)
|
||
// sVarname must NOT be unique. you can use the same sVarname with a different data-type
|
||
//
|
||
// Original function is not very reliable, because it is using the areas object-id, which is
|
||
// a runtime generated ID. Stored locations may turn invalid in case you change the area layout in the toolset.
|
||
// (e.g. deleting old areas)
|
||
//
|
||
// This function is 100% reliable, as long as you use unique TAGs for your areas
|
||
location NBDE_GetCampaignLocation(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID);
|
||
|
||
// This will read a vector from the specified campaign database
|
||
// The database name IS case sensitive and it must be the same for both set and get functions.
|
||
// If you want a variable to pertain to a specific player in the game, provide a player object.
|
||
//
|
||
// Improvements to original bioware function:
|
||
// Improved reading speed...
|
||
// There is no limit on the length of sVarname (original function is limited to 32 chars)
|
||
// sVarname must NOT be unique. you can use the same sVarname with a different data-type
|
||
vector NBDE_GetCampaignVector(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID);
|
||
|
||
// this will remove an integer from the specified campaign database
|
||
//
|
||
// Improvements to original bioware function:
|
||
// This will physically delete the variable from the database, not only flagging it
|
||
// Database will shrink in size
|
||
// No need to pack your database ever
|
||
void NBDE_DeleteCampaignInt(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID);
|
||
|
||
// this will remove a float from the specified campaign database
|
||
//
|
||
// Improvements to original bioware function:
|
||
// This will physically delete the variable from the database, not only flagging it
|
||
// Database will shrink in size
|
||
// No need to pack your database ever
|
||
void NBDE_DeleteCampaignFloat(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID);
|
||
|
||
// This will remove a string from the specified campaign database
|
||
//
|
||
// Improvements to original bioware function:
|
||
// This will physically delete the variable from the database, not only flagging it
|
||
// Database will shrink in size
|
||
// No need to pack your database ever
|
||
void NBDE_DeleteCampaignString(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID);
|
||
|
||
// This will remove a location from the specified campaign database
|
||
//
|
||
// Improvements to original bioware function:
|
||
// This will physically delete the variable from the database, not only flagging it
|
||
// Database will shrink in size
|
||
// No need to pack your database ever
|
||
void NBDE_DeleteCampaignLocation(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID);
|
||
|
||
// This will remove a vector from the specified campaign database
|
||
//
|
||
// Improvements to original bioware function:
|
||
// This will physically delete the variable from the database, not only flagging it
|
||
// Database will shrink in size
|
||
// No need to pack your database ever
|
||
void NBDE_DeleteCampaignVector(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID);
|
||
|
||
// This will flush a database to disk with a SINGLE StoreCampaignObject() call
|
||
//
|
||
// Don't use this function in a rapid manner.
|
||
// Delay each call to this function by at least 1 second (using delaycommand)
|
||
// in order to eliminate possible spikes...
|
||
void NBDE_FlushCampaignDatabase(string sCampaignName);
|
||
|
||
// NBDE databases are kept in memory. this commands unloads
|
||
// the database with the name sCampaignName from memory.
|
||
//
|
||
// Useful to unload databases you don't need often.
|
||
// Unloading/reloading is quite fast, so don't hesitate to use
|
||
// this regulary...
|
||
//
|
||
// Reloading happens automatically, btw...
|
||
void NBDE_UnloadCampaignDatabase(string sCampaignName);
|
||
|
||
|
||
// --------------------------- IMPLEMENTATION ----------------------------
|
||
/* ----------------------------------------------------------------------- */
|
||
|
||
// everything not in here gets considered an illegal character
|
||
// - mixed up for additional security
|
||
const string HASH_INDEX = "#i!j$k%l{&M/n(o)p=q?r^<5E>Xs`Tu'v]AwBxCyDzE1F2-G3t;4I}5Y:J6_K7+Z[Lm9N\ l0kOjPhQ,gRfSeHdU8cVbWa.";
|
||
|
||
const int HASH_PRIME = 3021377;
|
||
|
||
// simple hash
|
||
// returns -1 if string contains illegal character
|
||
int NBDE_Hash(string sData)
|
||
{
|
||
int nLen = GetStringLength(sData);
|
||
int i, nHash, nChar;
|
||
for(i=0;i<nLen;i++)
|
||
{
|
||
nChar = FindSubString(HASH_INDEX, GetSubString(sData,i,1));
|
||
if(nChar == -1) return -1;
|
||
nHash = ((nHash<<5) ^ (nHash>>27)) ^ nChar;
|
||
}
|
||
return nHash % HASH_PRIME;
|
||
}
|
||
|
||
// serialize location to padded string
|
||
string NBDE_LocationToString(location lLoc)
|
||
{
|
||
// serialization garbage... more or less "redo if it screws" code
|
||
string sLoc = IntToString(FloatToInt(GetPositionFromLocation(lLoc).x*100));
|
||
sLoc = (GetStringLength(sLoc) < 5) ? sLoc + GetStringLeft(" ",5 - GetStringLength(sLoc)) : GetStringLeft(sLoc,5);
|
||
sLoc += IntToString(FloatToInt(GetPositionFromLocation(lLoc).y*100));
|
||
sLoc = (GetStringLength(sLoc) < 10) ? sLoc + GetStringLeft(" ",10 - GetStringLength(sLoc)) : GetStringLeft(sLoc,10);
|
||
sLoc += IntToString(FloatToInt(GetPositionFromLocation(lLoc).z*100));
|
||
sLoc = (GetStringLength(sLoc) < 15) ? sLoc + GetStringLeft(" ",15 - GetStringLength(sLoc)) : GetStringLeft(sLoc,15);
|
||
sLoc += IntToString(FloatToInt(GetFacingFromLocation(lLoc)*100));
|
||
sLoc = (GetStringLength(sLoc) < 20) ? sLoc + GetStringLeft(" ",20 - GetStringLength(sLoc)) : GetStringLeft(sLoc,20);
|
||
sLoc += GetTag(GetAreaFromLocation(lLoc));
|
||
sLoc = (GetStringLength(sLoc) < 52) ? sLoc + GetStringLeft(" ",52 - GetStringLength(sLoc)) : GetStringLeft(sLoc,52);
|
||
return sLoc;
|
||
}
|
||
|
||
// de-serialize string to location
|
||
location NBDE_StringToLocation(string sLoc)
|
||
{
|
||
// fast de-serialize code using padded strings
|
||
vector vVec;
|
||
// build vector
|
||
vVec.x = StringToFloat(GetStringLeft(sLoc,5)) / 100;
|
||
vVec.y = StringToFloat(GetSubString(sLoc,5,5)) / 100;
|
||
vVec.z = StringToFloat(GetSubString(sLoc,10,5)) / 100;;
|
||
int nPad = FindSubString(GetSubString(sLoc, 20,32)," ");
|
||
// build & return location
|
||
return Location(GetObjectByTag((nPad != -1) ? GetSubString(sLoc, 20,nPad) : GetSubString(sLoc, 20,32)), vVec, StringToFloat(GetSubString(sLoc,15,5)) / 100);
|
||
}
|
||
|
||
// serialize vector to padded string
|
||
string NBDE_VectorToString(vector vVec)
|
||
{
|
||
// serialization garbage... more or less "redo if it screws" code
|
||
string sVec = IntToString(FloatToInt(vVec.x*100));
|
||
sVec = (GetStringLength(sVec) < 5) ? sVec + GetStringLeft(" ",5 - GetStringLength(sVec)) : GetStringLeft(sVec,5);
|
||
sVec += IntToString(FloatToInt(vVec.y*100));
|
||
sVec = (GetStringLength(sVec) < 10) ? sVec + GetStringLeft(" ",10 - GetStringLength(sVec)) : GetStringLeft(sVec,10);
|
||
sVec += IntToString(FloatToInt(vVec.z*100));
|
||
sVec = (GetStringLength(sVec) < 15) ? sVec + GetStringLeft(" ",15 - GetStringLength(sVec)) : GetStringLeft(sVec,15);
|
||
return sVec;
|
||
}
|
||
|
||
vector NBDE_StringToVector(string sVec)
|
||
{
|
||
// fast de-serialize code using padded strings
|
||
vector vVec;
|
||
vVec.x = StringToFloat(GetStringLeft(sVec,5)) / 100;
|
||
vVec.y = StringToFloat(GetSubString(sVec,5,5)) / 100;
|
||
vVec.z = StringToFloat(GetSubString(sVec,10,5)) / 100;
|
||
return vVec;
|
||
}
|
||
|
||
// returns player key with hopefully safe delimiter
|
||
string NBDE_GetPlayerKey(object oPC)
|
||
{
|
||
return GetName(oPC)+"<22>"+GetPCPlayerName(oPC);
|
||
}
|
||
|
||
// returns database object for the specified campaign database
|
||
//
|
||
// - auto-creates database object in case it doesn't exist
|
||
// - builds index for fast access
|
||
//
|
||
// you usually don't need to use this function directly...
|
||
object NBDE_GetCampaignDatabaseObject(string sCampaignName)
|
||
{
|
||
// get database item
|
||
object oDatabase = GetLocalObject(GetObjectByTag(NBDE_VAULT_TAG), NBDE_INDEX_PREFIX + sCampaignName);
|
||
// retrieve/create database if not indexed already
|
||
if(!GetIsObjectValid(oDatabase))
|
||
{
|
||
// get database vault object
|
||
// this container holds all database objects/items
|
||
object oVault = GetObjectByTag(NBDE_VAULT_TAG);
|
||
// check for valid vault
|
||
if(!GetIsObjectValid(oVault))
|
||
{
|
||
WriteTimestampedLogEntry("NBDE> Error: unable to locate '"+NBDE_VAULT_TAG+"' vault container object");
|
||
return OBJECT_INVALID;
|
||
}
|
||
// one time load
|
||
oDatabase = RetrieveCampaignObject(sCampaignName, NBDE_DATABASE_ITEM_VARNAME, GetLocation(oVault), oVault);
|
||
// not found ? create it
|
||
if(!GetIsObjectValid(oDatabase)) oDatabase = CreateItemOnObject(NBDE_DATABASE_ITEM_RESREF, oVault);
|
||
// check for valid database object
|
||
if(!GetIsObjectValid(oDatabase))
|
||
{
|
||
WriteTimestampedLogEntry("NBDE> Error: unable to create '"+sCampaignName+"' database object");
|
||
return OBJECT_INVALID;
|
||
}
|
||
// index item for fast access
|
||
SetLocalObject(oVault, NBDE_INDEX_PREFIX + sCampaignName, oDatabase);
|
||
}
|
||
return oDatabase;
|
||
}
|
||
|
||
// this will flush (aka write to disk) the specified campaign database in one big swoop
|
||
//
|
||
// don't use this function in a rapid manner.
|
||
// delay each subsequent call to this function by at least 1 second (using delaycommand)
|
||
// this way you completely eliminate cpu-spikes, no matter how many database
|
||
// you flush.
|
||
void NBDE_FlushCampaignDatabase(string sCampaignName)
|
||
{
|
||
// get database vault, it holds all database items
|
||
object oVault = GetObjectByTag(NBDE_VAULT_TAG);
|
||
if(GetIsObjectValid(oVault))
|
||
{
|
||
// get database item
|
||
object oDatabase = GetLocalObject(oVault, NBDE_INDEX_PREFIX + sCampaignName);
|
||
// store the whole database via one single StoreCampaignObject call
|
||
// all variables on the item get stored with the item
|
||
if(GetIsObjectValid(oDatabase))
|
||
{
|
||
// delete database on each flush to keep it compact and clean
|
||
DestroyCampaignDatabase(sCampaignName);
|
||
// store database
|
||
StoreCampaignObject(sCampaignName, NBDE_DATABASE_ITEM_VARNAME , oDatabase);
|
||
}
|
||
// database not loaded, no need to flush...
|
||
}
|
||
else // vault container missing
|
||
WriteTimestampedLogEntry("NBDE> Error: unable to locate '"+NBDE_VAULT_TAG+"' vault container object");
|
||
}
|
||
|
||
void NBDE_UnloadCampaignDatabase(string sCampaignName)
|
||
{
|
||
// get database vault, it holds all database items
|
||
object oVault = GetObjectByTag(NBDE_VAULT_TAG);
|
||
if(GetIsObjectValid(oVault))
|
||
{
|
||
// get database item
|
||
object oDatabase = GetLocalObject(oVault, NBDE_INDEX_PREFIX + sCampaignName);
|
||
if(GetIsObjectValid(oDatabase))
|
||
{
|
||
// delete index
|
||
DeleteLocalObject(oVault, NBDE_INDEX_PREFIX + sCampaignName);
|
||
// delete database object
|
||
DestroyObject(oDatabase);
|
||
}
|
||
// database not loaded, do nothing
|
||
}
|
||
else // vault container missing
|
||
WriteTimestampedLogEntry("NBDE> Error: unable to locate '"+NBDE_VAULT_TAG+"' vault container object");
|
||
}
|
||
|
||
void NBDE_SetCampaignInt(string sCampaignName, string sVarname, int nInt, object oPlayer = OBJECT_INVALID)
|
||
{
|
||
SetLocalInt(NBDE_GetCampaignDatabaseObject(sCampaignName) ,
|
||
((GetIsObjectValid(oPlayer)) ? NBDE_GetPlayerKey(oPlayer) : "") + sVarname, nInt );
|
||
}
|
||
|
||
void NBDE_SetCampaignFloat(string sCampaignName, string sVarname, float fFloat, object oPlayer = OBJECT_INVALID)
|
||
{
|
||
SetLocalFloat(NBDE_GetCampaignDatabaseObject(sCampaignName) ,
|
||
((GetIsObjectValid(oPlayer)) ? NBDE_GetPlayerKey(oPlayer) : "") + sVarname, fFloat);
|
||
}
|
||
|
||
void NBDE_SetCampaignString(string sCampaignName, string sVarname, string sString, object oPlayer = OBJECT_INVALID)
|
||
{
|
||
SetLocalString(NBDE_GetCampaignDatabaseObject(sCampaignName) ,
|
||
((GetIsObjectValid(oPlayer)) ? NBDE_GetPlayerKey(oPlayer) : "") + sVarname, sString);
|
||
}
|
||
|
||
void NBDE_SetCampaignLocation(string sCampaignName, string sVarname, location locLocation, object oPlayer = OBJECT_SELF)
|
||
{
|
||
SetLocalString( NBDE_GetCampaignDatabaseObject(sCampaignName) ,
|
||
NBDE_LOC_PREFIX + ((GetIsObjectValid(oPlayer)) ? NBDE_GetPlayerKey(oPlayer) : "") + sVarname ,
|
||
NBDE_LocationToString(locLocation) );
|
||
}
|
||
|
||
void NBDE_SetCampaignVector(string sCampaignName, string sVarname, vector vVector, object oPlayer = OBJECT_SELF)
|
||
{
|
||
SetLocalString(NBDE_GetCampaignDatabaseObject(sCampaignName) ,
|
||
NBDE_VEC_PREFIX + ((GetIsObjectValid(oPlayer)) ? NBDE_GetPlayerKey(oPlayer) : "") + sVarname ,
|
||
NBDE_VectorToString(vVector) );
|
||
}
|
||
|
||
int NBDE_GetCampaignInt(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID)
|
||
{
|
||
return GetLocalInt(NBDE_GetCampaignDatabaseObject(sCampaignName) ,
|
||
((GetIsObjectValid(oPlayer)) ? NBDE_GetPlayerKey(oPlayer) : "") + sVarname );
|
||
}
|
||
|
||
float NBDE_GetCampaignFloat(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID)
|
||
{
|
||
return GetLocalFloat(NBDE_GetCampaignDatabaseObject(sCampaignName) ,
|
||
((GetIsObjectValid(oPlayer)) ? NBDE_GetPlayerKey(oPlayer) : "") + sVarname );
|
||
}
|
||
|
||
string NBDE_GetCampaignString(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID)
|
||
{
|
||
return GetLocalString(NBDE_GetCampaignDatabaseObject(sCampaignName) ,
|
||
((GetIsObjectValid(oPlayer)) ? NBDE_GetPlayerKey(oPlayer) : "") + sVarname );
|
||
}
|
||
|
||
location NBDE_GetCampaignLocation(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID)
|
||
{
|
||
return NBDE_StringToLocation( GetLocalString(NBDE_GetCampaignDatabaseObject(sCampaignName) ,
|
||
NBDE_LOC_PREFIX + ((GetIsObjectValid(oPlayer)) ? NBDE_GetPlayerKey(oPlayer) : "") + sVarname) );
|
||
}
|
||
|
||
vector NBDE_GetCampaignVector(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID)
|
||
{
|
||
return NBDE_StringToVector( GetLocalString(NBDE_GetCampaignDatabaseObject(sCampaignName),
|
||
NBDE_VEC_PREFIX + ((GetIsObjectValid(oPlayer)) ? NBDE_GetPlayerKey(oPlayer) : "") + sVarname) );
|
||
}
|
||
|
||
void NBDE_DeleteCampaignInt(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID)
|
||
{
|
||
DeleteLocalInt(NBDE_GetCampaignDatabaseObject(sCampaignName) ,
|
||
((GetIsObjectValid(oPlayer)) ? NBDE_GetPlayerKey(oPlayer) : "") + sVarname);
|
||
}
|
||
|
||
void NBDE_DeleteCampaignFloat(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID)
|
||
{
|
||
DeleteLocalFloat(NBDE_GetCampaignDatabaseObject(sCampaignName) ,
|
||
((GetIsObjectValid(oPlayer)) ? NBDE_GetPlayerKey(oPlayer) : "") + sVarname);
|
||
}
|
||
|
||
void NBDE_DeleteCampaignString(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID)
|
||
{
|
||
DeleteLocalString(NBDE_GetCampaignDatabaseObject(sCampaignName) ,
|
||
((GetIsObjectValid(oPlayer)) ? NBDE_GetPlayerKey(oPlayer) : "") + sVarname);
|
||
}
|
||
|
||
void NBDE_DeleteCampaignLocation(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID)
|
||
{
|
||
DeleteLocalString(NBDE_GetCampaignDatabaseObject(sCampaignName) ,
|
||
NBDE_LOC_PREFIX + ((GetIsObjectValid(oPlayer)) ? NBDE_GetPlayerKey(oPlayer) : "") + sVarname);
|
||
}
|
||
|
||
void NBDE_DeleteCampaignVector(string sCampaignName, string sVarname, object oPlayer = OBJECT_INVALID)
|
||
{
|
||
DeleteLocalString(NBDE_GetCampaignDatabaseObject(sCampaignName) ,
|
||
NBDE_VEC_PREFIX + ((GetIsObjectValid(oPlayer)) ? NBDE_GetPlayerKey(oPlayer) : "") + sVarname);
|
||
}
|
||
|
||
|