logo logo

 Back to main page

The NWNX Community Forum

 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
 
Looking for Some Letoscript Info
Goto page 1, 2  Next
 
Post new topic   Reply to topic    nwnx.org Forum Index -> Scripts and Modules
View previous topic :: View next topic  
Author Message
Zunath



Joined: 06 Jul 2006
Posts: 183

PostPosted: Mon Nov 12, 2007 1:13    Post subject: Looking for Some Letoscript Info Reply with quote

I was looking around for some info about letoscript but didn't find much.

Can someone tell me if it's possible to modify a player's stats such as STR, DEX, HP, etc using letoscript?

If so, where can I pick up letoscript at and what script do I include to my own?

Thanks!
Back to top
View user's profile Send private message
Squatting Monk



Joined: 28 Jun 2007
Posts: 76

PostPosted: Thu Nov 15, 2007 3:13    Post subject: Reply with quote

Yes, all of those are possible. LetoScript is a very powerful tool, but it's difficult to start using (at least, it has been for me). The LetoScript forums are your best bet for getting information on it.
Back to top
View user's profile Send private message
william_hunter



Joined: 31 Jan 2007
Posts: 149

PostPosted: Sun Nov 18, 2007 5:56    Post subject: Reply with quote

Actually, I found it to be not too bad. Check out their forums, and you should be able to find lots of valuable info. Once you get things rolling, its easy.

For an option, you might want to check out Funky's SimTools though, he has all sorts of Letoscripting in place already, in a nice shiny package.
_________________
The Realm of Tharagon NWN PW
Back to top
View user's profile Send private message
Zunath



Joined: 06 Jul 2006
Posts: 183

PostPosted: Thu Nov 29, 2007 23:55    Post subject: Reply with quote

Thanks guys. I have SIMTools and I know it uses letoscript but I can't seem to find any scripts relating to it. No include files with the functions needed or anything like that.

Where do I get these? Or what are they named?

Thanks again!
Back to top
View user's profile Send private message
william_hunter



Joined: 31 Jan 2007
Posts: 149

PostPosted: Fri Nov 30, 2007 23:01    Post subject: Reply with quote

Its all included in the scripts prefaced by fky_. Check those in your mod after you import the SimTools newest version. As long as you have your databases all set up right and have the Letoscript plugin onboard, you should be ready to rock and roll.
_________________
The Realm of Tharagon NWN PW
Back to top
View user's profile Send private message
Zunath



Joined: 06 Jul 2006
Posts: 183

PostPosted: Tue Dec 04, 2007 22:12    Post subject: Reply with quote

Alright so I have letoscript installed and it's working great. But now I'm having some problems with the functions they posted on their boards. I posted for help on their too but seeing as they don't get much activity there I'm trying here.

I'm using these includes. Sorry they're so long.

"inc_letoscript"
Code:
 //#include "inc_utility"

//defining directories
//must be changed to each install
//it will use a local string on the module named NWN_DIR if set


const string DB_NAME = "prcnwnxleto";
const string DB_GATEWAY_VAR = "prcnwnxleto";

//set this to true if using build 18 or earlier of letoscript.dll
//again this is a PRC switch


/*YOU MUST ADD THE FOLLOWING TO YOUR ON CLIENT EXIT EVENT

    object oPC = GetExitingObject();
    LetoPCExit(oPC);

*/

/*YOU MUST ADD THE FOLLOWING TO YOUR ON CLIENT ENTER EVENT

    object oPC = GetExitingObject();
    LetoPCEnter(oPC);

*/


///* local copies for easy redistribution out of the PRC

//these are the names of local variables, normally ints, to set on the module

//set this if using any letoscript
const string PRC_USE_LETOSCRIPT                      = "PRC_USE_LETOSCRIPT";

 //* Set this to 1 if using build 18
const string PRC_LETOSCRIPT_PHEONIX_SYNTAX           = "PRC_LETOSCRIPT_PHEONIX_SYNTAX";

 //* Letoscript needs a string named PRC_LETOSCRIPT_NWN_DIR set to the
 //* directory of NWN. If it doesnt work, try different slash options: // \\ / \
const string PRC_LETOSCRIPT_NWN_DIR                  = "PRC_LETOSCRIPT_NWN_DIR";

 //* Switch so that Unicorn will use the SQL database for SCO/RCO
 //* Must have the zeoslib.dlls installed for this
 //*
 //* UNTESTED!!!
const string PRC_LETOSCRIPT_UNICORN_SQL              = "PRC_LETOSCRIPT_UNICORN_SQL";

 //* This is a string, not integer.
 //* If the IP is set, Letoscript will use ActivatePortal instead of booting.
 //* The IP and Password must be correct for your server or bad things will happen.
 //* - If your IP is non-static make sure this is kept up to date.
 //*
 //* See the Lexicon entry on ActivatePortal for more information.
 //*
 //* @see PRC_LETOSCRIPT_PORTAL_PASSWORD
const string PRC_LETOSCRIPT_PORTAL_IP                = "PRC_LETOSCRIPT_PORTAL_IP";

 //* This is a string, not integer.
 //* If the IP is set, Letoscript will use ActivatePortal instead of booting.
 //* The IP and Password must be correct for your server or bad things will happen.
 //* - If your IP is non-static make sure this is kept up to date.
 //*
 //* See the Lexicon entry on ActivatePortal for more information.
 //*
 //* @see PRC_LETOSCRIPT_PORTAL_IP
const string PRC_LETOSCRIPT_PORTAL_PASSWORD          = "PRC_LETOSCRIPT_PORTAL_PASSWORD";

 //* If set you must be using Unicorn.
 //* Will use getnewest bic instead of filename reconstruction (which fails if
 //* multiple characters have the same name)
const string PRC_LETOSCRIPT_GETNEWESTBIC             = "PRC_LETOSCRIPT_GETNEWESTBIC";

// * Set this if you are using SQLite (the built-in database in NWNX-ODBC2).
// * This will use transactions and SQLite specific syntax.
const string PRC_DB_SQLLITE                          = "PRC_DB_SQLLITE";

const int PRC_SQL_ERROR = 0;
const int PRC_SQL_SUCCESS = 1;
// Function defintions
int GetPRCSwitch(string sSwitch);
void PRC_SQLExecDirect(string sSQL);

void PRC_SQLInit()
{
    int i;

    // Placeholder for ODBC persistence
    string sMemory;

    for (i = 0; i < 8; i++)     // reserve 8*128 bytes
        sMemory +=
            "................................................................................................................................";

    SetLocalString(GetModule(), "NWNX!ODBC!SPACER", sMemory);
}

void PRC_SQLExecDirect(string sSQL)
{
//PrintString(sSQL);
    SetLocalString(GetModule(), "NWNX!ODBC!EXEC", sSQL);
}

int PRC_SQLFetch()
{
    string sRow;
    object oModule = GetModule();

    SetLocalString(oModule, "NWNX!ODBC!FETCH", GetLocalString(oModule, "NWNX!ODBC!SPACER"));
    sRow = GetLocalString(oModule, "NWNX!ODBC!FETCH");
    if (GetStringLength(sRow) > 0)
    {
        SetLocalString(oModule, "NWNX_ODBC_CurrentRow", sRow);
        return PRC_SQL_SUCCESS;
    }
    else
    {
        SetLocalString(oModule, "NWNX_ODBC_CurrentRow", "");
        return PRC_SQL_ERROR;
    }
}

string PRC_SQLGetTick()
{
    string sTick;
    if(GetPRCSwitch(PRC_DB_SQLLITE))
        sTick = "";
    else
        sTick = "`";
    return sTick;
}

string PRC_SQLGetData(int iCol)
{
    int iPos;
    string sResultSet = GetLocalString(GetModule(), "NWNX_ODBC_CurrentRow");

    // find column in current row
    int iCount = 0;
    string sColValue = "";

    iPos = FindSubString(sResultSet, "¬");
    if ((iPos == -1) && (iCol == 1))
    {
        // only one column, return value immediately
        sColValue = sResultSet;
    }
    else if (iPos == -1)
    {
        // only one column but requested column > 1
        sColValue = "";
    }
    else
    {
        // loop through columns until found
        while (iCount != iCol)
        {
            iCount++;
            if (iCount == iCol)
                sColValue = GetStringLeft(sResultSet, iPos);
            else
            {
                sResultSet = GetStringRight(sResultSet, GetStringLength(sResultSet) - iPos - 1);
                iPos = FindSubString(sResultSet, "¬");
            }

            // special case: last column in row
            if (iPos == -1)
                iPos = GetStringLength(sResultSet);
        }
    }

    return sColValue;
}


string ReplaceSingleChars(string sString, string sTarget, string sReplace)
{
    if (FindSubString(sString, sTarget) == -1) // not found
        return sString;

    int i;
    string sReturn = "";
    string sChar;

    // Loop over every character and replace special characters
    for (i = 0; i < GetStringLength(sString); i++)
    {
        sChar = GetSubString(sString, i, 1);
        if (sChar == sTarget)
            sReturn += sReplace;
        else
            sReturn += sChar;
    }
    return sReturn;
}

int GetPRCSwitch(string sSwitch)
{
    return GetLocalInt(GetModule(), sSwitch);
}

void DoDebug(string sString, object oAdditionalRecipient = OBJECT_INVALID)
{
    SendMessageToPC(GetFirstPC(), sString);
    if(oAdditionalRecipient != OBJECT_INVALID)
        SendMessageToPC(oAdditionalRecipient, sString);
    WriteTimestampedLogEntry(sString);
}

//*/

//instanty runs the letoscript sScript
//for sType see abive
//if sType is POLL, PollThread is atomatically started
//and sPollScript is passed as the script name
string LetoScript(string sScript, string sType = "SCRIPT", string sPollScript = "");

//This command adds the script to the cuttent superscript
//to run the superscript use StackedLetoScripRun
void StackedLetoScript(string sScript);

//poll an existing thread
//when the thread is finished, script sScript is run
void PollThread(string sThreadID, string sScript);

//credit to demux
//gets a bicpath of a pc
//must be servervault to work
string GetBicPath(object oPC);

//credit to demux
//gets the filename of a PCs bic
//must be servervault
string GetBicFileName(object oPC);

//This will automatically add the required code before and after, and will
//adapt based on PC/NPC/etc.
//This overwites the existing object which will break stored references
//such as henchmen. The new object is returned.
//the result of the script is stored on the module in LetoResult for 1 second
//if nDestroyOriginal is set then PCs will be booted and non-pcs will be destroyed
object RunStackedLetoScriptOnObject(object oObject, string sLetoTag = "OBJECT",    string sType = "SCRIPT", string sPollScript = "", int nDestroyOriginal = TRUE);

//const int DEBUG = TRUE;

string GetNWNDir()
{
    string sReturn = GetLocalString(GetModule(), PRC_LETOSCRIPT_NWN_DIR);
    /*
    if(GetStringRight(sReturn, 1) != "\"
        && GetStringRight(sReturn, 1) != "/")
        sReturn += "\";
        //" this is here so textpad doesnt go screwy becasue it escapes the quotes above.
        */
    return sReturn;
}

//credit to demux
string GetBicFileName(object oPC)
{
    string sChar, sBicName;
    string sPCName = GetStringLowerCase(GetName(oPC));
    int i, iNameLength = GetStringLength(sPCName);

    for(i=0; i < iNameLength; i++) {
        sChar = GetSubString(sPCName, i, 1);
        if (TestStringAgainstPattern("(*a|*n|*w|'|-|_)", sChar)) {
            if (sChar != " ") sBicName += sChar;
        }
    }
    return GetStringLeft(sBicName, 16);
}

//credit to demux
string GetBicPath(object oPC)
{
    // Gets a local var stored on oPC on "event client enter". I do this because
    // "on even client leave", function GetPCPlayerName() can not be used. Since
    // a .bic file can not be changed while the owner is logged in, it is typical
    // to execute leto scripts when the client leaves (on event client leave).
    string PlayerName = GetLocalString(oPC, "PlayerName");
    if(PlayerName == "")
        PlayerName = GetPCPlayerName(oPC);

    // Retruns the full path to a .bic file.
    return GetNWNDir()+"servervault/"+PlayerName+"/"+GetBicFileName(oPC)+".bic";
}

void VoidLetoScript(string sScript, string sType = "SCRIPT", string sPollScript = "")
{
    LetoScript(sScript,sType,sPollScript);
}

string LetoScript(string sScript, string sType = "SCRIPT", string sPollScript = "")
{
    string sAnswer;
    DoDebug(sType+" >: "+sScript);
    SetLocalString(GetModule(), "NWNX!LETO!"+sType, sScript);
    sAnswer = GetLocalString(GetModule(), "NWNX!LETO!"+sType);
    DoDebug(sType+" <: "+sAnswer);
    if(sType == "SPAWN")
        DelayCommand(1.0, PollThread(sAnswer, sPollScript));
    return sAnswer;
}

void LetoPCEnter(object oPC)
{
    SetLocalString(oPC, "Leto_Path", GetBicPath(oPC));
    SetLocalString(oPC, "PCPlayerName", GetPCPlayerName(oPC));
    DeleteLocalString(oPC, "LetoScript");
}

void LetoPCExit(object oPC)
{
    string sScript = GetLocalString(oPC, "LetoScript");
    if(sScript != "")
    {
        string sPath = GetLocalString(oPC, "Leto_Path");
        if(sPath == "")
            DoDebug("Path is Null");
        if(GetPRCSwitch(PRC_LETOSCRIPT_PHEONIX_SYNTAX))
        {
            //pheonix syntax
            sScript  = "<file:open CHAR <qq:"+sPath+">>"+sScript;
            sScript += "<file:save CHAR <qq:"+sPath+">>";
            sScript += "<file:close CHAR >";
        }
        else
        {
            if(GetPRCSwitch(PRC_LETOSCRIPT_GETNEWESTBIC))
            {
                sScript  = "%char =  FindNewestBic('"+GetNWNDir()+"servervault/"+GetLocalString(oPC, "PCPlayerName")+"'); "+sScript;
                sScript += "%char = '>'; ";
                sScript += "close %char; ";
            }
            else
            {
                //unicorn syntax
                sScript  = "%char= '"+sPath+"'; "+sScript;
                sScript += "%char = '>'; ";
                sScript += "close %char; ";
            }
        }
        string sScriptResult = LetoScript(sScript);
        SetLocalString(GetModule(), "LetoResult", sScriptResult);
        AssignCommand(GetModule(), DelayCommand(1.0, DeleteLocalString(GetModule(), "LetoResult")));
    }
}

void StackedLetoScript(string sScript)
{
    DoDebug("SLS :"+sScript);
    SetLocalString(GetModule(), "LetoScript", GetLocalString(GetModule(), "LetoScript")+ sScript);
}

void PollThread(string sThreadID, string sScript)
{
    if(GetLocalInt(GetModule(), "StopThread"+sThreadID) == TRUE)
        return;
    DoDebug("Polling: "+sThreadID);
    //add blank space to capture error messages
    string sResult = LetoScript(sThreadID+"                                   "
        +"                                   "
        +"                                   "
        +"                                   "
        +"                                   "
        +"                                   "
        +"                                   "
        +"                                   "
        +"                                   ", "POLL");
    if(sResult == "Error: "+sThreadID+" not done.")
    {
        DelayCommand(1.0, PollThread(sThreadID, sScript));
        return;
    }
    else
    {
        DoDebug("Poll: Executing: "+sScript);
        SetLocalInt(GetModule(), "StopThread"+sThreadID, TRUE);
        DelayCommand(6.0, DeleteLocalInt(GetModule(), "StopThread"+sThreadID));
        location lLoc = GetLocalLocation(GetModule(), "Thread"+sThreadID+"_loc");
        DelayCommand(1.0, DeleteLocalLocation(GetModule(), "Thread"+sThreadID+"_loc"));
DoDebug("Thread"+sThreadID+"_loc");
DoDebug(GetName(GetAreaFromLocation(lLoc)));
        object oReturn;
        if(GetPRCSwitch(PRC_LETOSCRIPT_PHEONIX_SYNTAX))
        {
            oReturn = RetrieveCampaignObject(DB_NAME, DB_GATEWAY_VAR, lLoc);
        }
        else
        {
            if(GetPRCSwitch(PRC_LETOSCRIPT_UNICORN_SQL))
            {
                string sSQL = "SELECT blob FROM "+DB_NAME+" WHERE "+DB_GATEWAY_VAR+"="+DB_GATEWAY_VAR+" LIMIT 1";
                SetLocalString(GetModule(), "NWNX!ODBC!SETSCORCOSQL", sSQL);
                oReturn = RetrieveCampaignObject("NWNX", "-", lLoc);
            }
            else
            {
                oReturn = RetrieveCampaignObject(DB_NAME, DB_GATEWAY_VAR, lLoc);
            }
        }
DoDebug(GetName(oReturn));
        SetLocalString(GetModule(), "LetoResult", sResult);
        AssignCommand(GetModule(), DelayCommand(1.0, DeleteLocalString(GetModule(), "LetoResult")));
        SetLocalObject(GetModule(), "LetoResultObject", oReturn);
        AssignCommand(GetModule(), DelayCommand(1.0, DeleteLocalObject(GetModule(), "LetoResultObject")));
        SetLocalString(GetModule(), "LetoResultThread", sThreadID);
        AssignCommand(GetModule(), DelayCommand(1.0, DeleteLocalString(GetModule(), "LetoResultThread")));
        ExecuteScript(sScript, OBJECT_SELF);
    }
}

void VoidRunStackedLetoScriptOnObject(object oObject, string sLetoTag = "OBJECT",
    string sType = "SCRIPT", string sPollScript = "", int nDestroyOriginal = TRUE)
{
    RunStackedLetoScriptOnObject(oObject,sLetoTag,sType,sPollScript,nDestroyOriginal);
}

object RunStackedLetoScriptOnObject(object oObject, string sLetoTag = "OBJECT",
    string sType = "SCRIPT", string sPollScript = "", int nDestroyOriginal = TRUE)
{
    if(!GetIsObjectValid(oObject))
    {
        WriteTimestampedLogEntry("ERROR: "+GetName(oObject)+"is invalid");
        WriteTimestampedLogEntry("Script was "+GetLocalString(GetModule(), "LetoScript"));
        return OBJECT_INVALID;
    }
    string sCommand;
    object oReturn;
    location lLoc;
    object oWPLimbo = GetObjectByTag("HeartOfChaos");
    location lLimbo;
    if(GetIsObjectValid(oWPLimbo))
        lLimbo = GetLocation(oWPLimbo);
    else
        lLimbo = GetStartingLocation();
    string sScript = GetLocalString(GetModule(), "LetoScript");
    DeleteLocalString(GetModule(), "LetoScript");
    string sScriptResult;
    //check if its a DM or PC
    //these use bic files
    if(GetIsPC(oObject) || GetIsDM(oObject))
    {
        if(!nDestroyOriginal)//dont boot
        {
            string sPath = GetLocalString(oObject, "Leto_Path");
            if(GetPRCSwitch(PRC_LETOSCRIPT_PHEONIX_SYNTAX))
            {
                sCommand = "<file:open '"+sLetoTag+"' <qq:"+sPath+">>";
                sScript = sCommand+sScript;
                sCommand = "<file:close '"+sLetoTag+"'>";
                sScript = sScript+sCommand;
                //unicorn
            }
            else
            {
                if(GetPRCSwitch(PRC_LETOSCRIPT_GETNEWESTBIC))
                {
                    sScript  = "%"+sLetoTag+" =  FindNewestBic('"+GetNWNDir()+"servervault/"+GetLocalString(oObject, "PCPlayerName")+"'); ";
                }
                else
                {
                    //unicorn syntax
                    sCommand = "%"+sLetoTag+" = '"+sPath+"'; "; //qq{} doesnt work for me at the moment, wrong slashes
                }
                sScript = sCommand+sScript;
                sCommand = "close %"+sLetoTag+"; ";
                sScript = sScript+sCommand;



            }
            sScriptResult = LetoScript(sScript, sType, sPollScript);
        }
        else//boot
        {
            //this triggers the OnExit code to fire the letoscript
            SetLocalString(oObject, "LetoScript", GetLocalString(oObject, "LetoScript")+sScript);
            if(GetLocalString(GetModule(), PRC_LETOSCRIPT_PORTAL_IP) == "")
            {
                BootPC(oObject);
            }
            else
            {
                ActivatePortal(oObject,
                    GetLocalString(GetModule(), PRC_LETOSCRIPT_PORTAL_IP),
                    GetLocalString(GetModule(), PRC_LETOSCRIPT_PORTAL_PASSWORD),
                    "", //waypoint, may need to change
                    TRUE);
            }
            return oReturn;
        }
    }
    //its an NPC/Placeable/Item, go through DB
    else if(GetObjectType(oObject) == OBJECT_TYPE_CREATURE
        || GetObjectType(oObject) == OBJECT_TYPE_ITEM
        || GetObjectType(oObject) == OBJECT_TYPE_PLACEABLE
        || GetObjectType(oObject) == OBJECT_TYPE_STORE
        || GetObjectType(oObject) == OBJECT_TYPE_WAYPOINT)
    {
        if(GetPRCSwitch(PRC_LETOSCRIPT_PHEONIX_SYNTAX))
        {
            //Put object into DB
            StoreCampaignObject(DB_NAME, DB_GATEWAY_VAR, oObject);
            // Reaquire DB with new object in it
            sCommand += "<file:open FPT <qq:" + GetNWNDir() + "database/" + DB_NAME + ".fpt>>";
            //Extract object from DB
            sCommand += "<fpt:extract FPT '"+DB_GATEWAY_VAR+"' "+sLetoTag+">";
            sCommand += "<file:close FPT>";
            sCommand += "<file:use "+sLetoTag+">";
        }
        else
        {
            if(GetPRCSwitch(PRC_LETOSCRIPT_UNICORN_SQL))
            {
                //unicorn
                //Put object into DB
                string sSQL = "SELECT "+DB_GATEWAY_VAR+" FROM "+DB_NAME+" WHERE "+DB_GATEWAY_VAR+"="+DB_GATEWAY_VAR+" LIMIT 1";
                PRC_SQLExecDirect(sSQL);

                if (PRC_SQLFetch() == PRC_SQL_SUCCESS)
                {
                    // row exists
                    sSQL = "UPDATE "+DB_NAME+" SET val=%s WHERE "+DB_GATEWAY_VAR+"="+DB_GATEWAY_VAR;
                    SetLocalString(GetModule(), "NWNX!ODBC!SETSCORCOSQL", sSQL);
                }
                else
                {
                    // row doesn't exist
                    // assume table doesnt exist too
                    sSQL = "CREATE TABLE "+DB_NAME+" ( "+DB_GATEWAY_VAR+" TEXT, blob BLOB )";
                    PRC_SQLExecDirect(sSQL);
                    sSQL = "INSERT INTO "+DB_NAME+" ("+DB_GATEWAY_VAR+", blob) VALUES" +
                        "("+DB_GATEWAY_VAR+", %s)";
                    SetLocalString(GetModule(), "NWNX!ODBC!SETSCORCOSQL", sSQL);
                }
                StoreCampaignObject ("NWNX", "-", oObject);
                // Reaquire DB with new object in it
                //force data to be written to disk
                sSQL = "COMMIT";
                PRC_SQLExecDirect(sSQL);
                sCommand += "sql.connect 'root', '' or die $!; ";
                sCommand += "sql.query 'SELECT blob FROM "+DB_NAME+" WHERE "+DB_GATEWAY_VAR+"="+DB_GATEWAY_VAR+" LIMIT 1'; ";
                sCommand += "sql.retrieve %"+sLetoTag+"; ";
            }
            else
            {
                //Put object into DB
                StoreCampaignObject(DB_NAME, DB_GATEWAY_VAR, oObject);
                sCommand += "%"+sLetoTag+"; ";
                //Extract object from DB
                sCommand += "extract '"+GetNWNDir()+"database/"+DB_NAME+".fpt', '"+DB_GATEWAY_VAR+"', %"+sLetoTag+" or die $!;";
            }
        }
        //store their location
        lLoc = GetLocation(oObject);
        if(!GetIsObjectValid(GetAreaFromLocation(lLoc)))
            lLoc = GetStartingLocation();

        sScript = sCommand + sScript;
        sCommand = "";

        //destroy the original
        if(nDestroyOriginal)
        {
            AssignCommand(oObject, SetIsDestroyable(TRUE));
            DestroyObject(oObject);
        //its an NPC/Placeable/Item, go through DB
            if(GetPRCSwitch(PRC_LETOSCRIPT_PHEONIX_SYNTAX))
            {
                sCommand  = "<file:open FPT <qq:" + GetNWNDir() + "database/" + DB_NAME + ".fpt>>";
                sCommand += "<fpt:replace FPT '" +DB_GATEWAY_VAR+ "' "+sLetoTag+">";
                sCommand += "<file:save FPT>";
                sCommand += "<file:close FPT>";
                sCommand += "<file:close "+sLetoTag+">";
            }
            else
            {
                if(GetPRCSwitch(PRC_LETOSCRIPT_UNICORN_SQL))
                {
                    //unicorn
                    sCommand += "sql.query 'SELECT blob FROM "+DB_NAME+" WHERE "+DB_GATEWAY_VAR+"="+DB_GATEWAY_VAR+" LIMIT 1'; ";
                    sCommand += "sql.store %"+sLetoTag+"; ";
                    sCommand += "close %"+sLetoTag+"; ";
                }
                else
                {
                    sCommand += "inject '"+GetNWNDir()+"database/"+DB_NAME+".fpt', '"+DB_GATEWAY_VAR+"', %"+sLetoTag+" or die $!;";
                    sCommand += "close %"+sLetoTag+"; ";
                }
            }
        }
        else
        {
            if(GetPRCSwitch(PRC_LETOSCRIPT_PHEONIX_SYNTAX))
                sCommand += "<file:close "+sLetoTag+">";
            else
                sCommand += "close %"+sLetoTag+"; ";
        }

        sScript = sScript + sCommand;
        sScriptResult = LetoScript(sScript, sType, sPollScript);

        if(nDestroyOriginal && sType != "SPAWN")
        {
            if(GetPRCSwitch(PRC_LETOSCRIPT_PHEONIX_SYNTAX))
            {
                if(GetObjectType(oObject) == OBJECT_TYPE_CREATURE)
                {
                    oReturn = RetrieveCampaignObject(DB_NAME, DB_GATEWAY_VAR, lLimbo);
                    AssignCommand(oReturn, JumpToLocation(lLoc));
                }
                else
                    oReturn = RetrieveCampaignObject(DB_NAME, DB_GATEWAY_VAR, lLoc);
            }
            else
            {
                if(GetPRCSwitch(PRC_LETOSCRIPT_UNICORN_SQL))
                {
                    string sSQL = "SELECT blob FROM "+DB_NAME+" WHERE "+DB_GATEWAY_VAR+"="+DB_GATEWAY_VAR+" LIMIT 1";
                    SetLocalString(GetModule(), "NWNX!ODBC!SETSCORCOSQL", sSQL);
                    if(GetObjectType(oObject) == OBJECT_TYPE_CREATURE)
                    {
                        oReturn = RetrieveCampaignObject("NWNX", "-", lLimbo);
                        AssignCommand(oReturn, JumpToLocation(lLoc));
                    }
                    else
                        oReturn = RetrieveCampaignObject("NWNX", "-", lLoc);
                }
                else
                {
                    if(GetObjectType(oObject) == OBJECT_TYPE_CREATURE)
                    {
                        oReturn = RetrieveCampaignObject(DB_NAME, DB_GATEWAY_VAR, lLimbo);
                        AssignCommand(oReturn, JumpToLocation(lLoc));
                    }
                    else
                        oReturn = RetrieveCampaignObject(DB_NAME, DB_GATEWAY_VAR, lLoc);
                }
            }
        }
        else if(nDestroyOriginal && sType == "SPAWN")
        {
            SetLocalLocation(GetModule(), "Thread"+IntToString(StringToInt(sScriptResult))+"_loc", lLoc);
DoDebug("Thread"+IntToString(StringToInt(sScriptResult))+"_loc");
        }
    }
    SetLocalString(GetModule(), "LetoResult", sScriptResult);
    AssignCommand(GetModule(), DelayCommand(1.0, DeleteLocalString(GetModule(), "LetoResult")));

    return oReturn;
}

//void main(){}


and this one:

"inc_letocommands"

Code:
 /*
Primogenitors Letoscript Commands
These assume you are running a servervault game with NWNX2 and Letoscript v18
Leto is avaliable from http://sourceforge.net/projects/leto/
NNWNX2 is avaliable from http://nwvault.ign.com/Files/other/data/1046636009723.shtml

You should also customize the constants in inc_letoscript so that they point to
your neverwinter nights directory.

There are three steps to a letoscript change
1. Bring the object into letoscript
2. Give commands
3. Bring the object back to NWN

The first step is different for PCs and for NPCs/objects.
For PCs, you can load their .bic file directly.
However, when you apply the changes, they have to be offline.
For NPCs, you can save them in the bioware database, then have leto extract
them from there.
Use the LetoWorkWithObject for both of these, but remeber to boot PCs before
running the script

The second step is to create the commands and then run them.
This is what most of the functions in this file are for. They create the script
that leto understands. The results can be simply added together to create one long
string. Once all the commands are together, they are run on the object.

Finally you have to bring the object back into NWN. For PCs the changes will apply
from whenever they rejoin the server. For NPCs you do the opposite of extraction,
i.e. put them into the database then put them into the game.

Notes:
This may make characters illegal, so it is recommended that Enforce Legal Characters is off.
*/
#include "inc_letoscript"

//general setting a variable in letoscript function
//adds it if it doesnt exist
//replaces a value if it does exist
string LetoSet(string sLocation,string sValue, string sType, int bAdd = TRUE);

//general adjusting a variable in letoscript function
//wont work with stringtypes
string LetoAdjust(string sLocation, int nValue, string sType);

//deleting a field
string LetoDelete(string sLocation);

//get a field
string LetoGet(string sLocation);

string LetoAdd(string sLocation,string sValue, string sType)
{
    return LetoSet(sLocation, sValue, sType, TRUE);
}

string LetoSet(string sLocation,string sValue, string sType, int bAdd = TRUE)
{
//phoenix
// <gff:add 'FirstName' {type='string' value=<qq:Bob the Minogon> setifexists=True}>
//unicorn
// add /FirstName, Value => qq{Bob the Minogon}, Type => gffLocString, SetIfExists => TRUE;
    if(sType != "byte"
        && sType != "word"
        && sType != "int"
        && sType != "dword"
        && sType != "char"
        && sType != "short"
        && sType != "dword64"
        && sType != "int64"
        && sType != "float"
        && sType != "double"
        && sType != "list")
    {
        if(GetPRCSwitch(PRC_LETOSCRIPT_PHEONIX_SYNTAX))
          sValue = "<qq:"+sValue+">";
        else
            sValue = "qq{"+sValue+"}";
        //wrap strings in quotes, so it doest go awry
        //sValue = "'"+sValue+"'";
    }
    if(GetPRCSwitch(PRC_LETOSCRIPT_PHEONIX_SYNTAX))
    {
        string sReturn = "<gff:";
        //if(bAdd)
            sReturn +="add";
        //else
        //    sReturn +="set";
        sReturn += "'"+sLocation+"' {type='"+sType+"' ";
        if(sType != "list")
            sReturn += "value="+sValue+" ";
        if(!bAdd)
            sReturn += " setifexists=True";
        sReturn += "}> ";
        return  sReturn;
    }
//unicorn
    else
    {
        string sReturn = "add /"+sLocation+", ";
        if(sType != "list")
            sReturn += "Value => "+sValue+", ";
        sReturn += "Type => gff"+sType;
        if(bAdd)
            sReturn += ", SetIfExists => TRUE";
        sReturn += "; ";
        return sReturn;
    }
}

string LetoAdjust(string sLocation, int nValue, string sType)
{
//phoenix
// <gff:set 'Str' {type='byte' value=(<gff:get 'Str'>+2)}>
//unicorn
// /Str = /Str+2;
    string sValue = IntToString(nValue);
    if(nValue >= 0)
        sValue = "+"+sValue;
    if(GetPRCSwitch(PRC_LETOSCRIPT_PHEONIX_SYNTAX))
        return LetoSet(sLocation, "(<gff:get '"+sLocation+"'>"+sValue+")", sType);
//unicorn
    else
        return LetoSet(sLocation, "(/"+sLocation+sValue+")", sType);
}

//deleting a field
string LetoDelete(string sLocation)
{
//phoenix
// <gff:delete 'Str'>
//unicorn
// clear /Str;
    if(GetPRCSwitch(PRC_LETOSCRIPT_PHEONIX_SYNTAX))
        return "<gff:delete '"+sLocation+"'> ";
    else
        return "clear /"+sLocation+"; ";

}

//deleting a field
string LetoGet(string sLocation)
{
//phoenix
// <Str>
//unicorn
// /Str;
    if(GetPRCSwitch(PRC_LETOSCRIPT_PHEONIX_SYNTAX))
        return "<"+sLocation+">";
    else
        return "print /"+sLocation+";";

}

//Returns a script to set a name
//if bLastName is true, then its a last name
//otherwise its a first name.
//this only works with creatures
string SetCreatureName(string sName, int bLastName = FALSE);

//Returns a script to set a name
//this only works with items
string SetItemName(string sName);

//returns a script to set description
//for items this is unidentified description
//use SetIdentifiedDescription for an identified description
string SetDescription(string sDescription);

//returns a script to set an identified description
//only works with items
string SetIdentifiedDescription(string sDescription);

//returns a script to set an ability score
//this is an absolute setting, so racial bonuses
//RDD bonuses, and great X I-X feats will be in addition to this
//Non-ELC compliant
string SetAbility(int nAbility, int nScore);

//returns a script to adjust an ability score
//this is relative to the current value so use negative to lower
//and positive to raise
//Non-ELC compliant
string AdjustAbility(int nAbility, int nAdjustment);

//returns a script to specify a tail on the model
//see tailmodel.2da for possible values
string SetTail(int nTailID);

//returns a script to specify wings on the model
//see wingmodel.2da for possible values
string SetWings(int nWingsID);

//returns a script to set a skill score
//this is an absolute setting, so racial bonuses
//feat bonuses, ability bonuses and armor bonuses
//will be in addition to this
//Non-ELC compliant
string SetSkill(int nSkill, int nScore, int nLevel = 1);

//returns a script to adjust a skill score
//this is relative to the current value so use negative to lower
//and positive to raise
//Non-ELC compliant
string AdjustSkill(int nSkill, int nAdjustment, int nLevel = 1);

//returns a script to set the number of spare skill points
//this is absolute and replaces any existing value
//Non-ELC compliant
string SetSpareSkill(int nScore, int nLevel = 1);

//returns a script to adjust the number of spare skill points
//Non-ELC compliant
string AdjustSpareSkill(int nScore, int nLevel = 1);

//returns a script to change race
//this does not alter appearance, feats, or special abilities
//it only changes the racial type
//this will affect racial ability score modifiers however
//Non-ELC compliant
string SetRace(int nRace);

//returns a script to change hit points
//Non-ELC compliant
string AdjustHitPoints(int nHP, int nLevel = 1);

//returns a script to change gender
string SetGender(int nGender);

//returns a script to change skin color
//the values are based on the windows in the toolset
//start at 0 in top left
string SetSkinColor(int nColor);

//returns a script to change hair color
//the values are based on the windows in the toolset
//start at 0 in top left
string SetHairColor(int nColor);

//returns a script to change tatto color
//the values are based on the windows in the toolset
//start at 0 in top left
//nTattoo determines if its tattoo 1 or 2
string SetTatooColor(int nColor, int nTattoo);

//returns a script to change movement rate
//as defined in creaturespeed.2da
//may not work if its appearance linked
//Non-ELC compliant
string SetMovement(int nRate);

//returns a script to change soundset
//as defined in soundset.2da
string SetSoundset(int nSoundsetID);

//returns a script to change portrait
//as defined in portrats.2da
//this only works with PCs and adds the po_ to the start of the string
string SetPCPortrait(string sPortrait);

//returns a script to change portrait
//as defined in portrats.2da
//this only works with NPCs and is a 2da reference
string SetNPCPortrait(int nPortraitID);

//returns a script to change the script assigned to an event
//should work with PC or NPC
//uses the EVENT_* constants
string SetScript(int nEvent, string sScript);

//returns a script to set the value of a save
//this is absolute and replaces any existing value
//Non-ELC compliant
string SetSave(int nSaveType, int nSave);

//returns a script to adjust a save score
//this is relative to the current value so use negative to lower
//and positive to raise
//Non-ELC compliant
string AdjustSave(int nSaveType, int nAdjustment);

//returns a script to add a feat
//Non-ELC compliant
string AddFeat(int nFeat, int nLevel = 1);

//returns a script to remove a feat
//Non-ELC compliant
string RemoveFeat(int nFeat);

//returns a script to add a special ability
//credit to demux
string AddSpecialAbility(int iSpell = -1, int iAmount = 1, int iLevel = 1);

//returns a script to specify AC
string SetNaturalAC(int nAC);

//returns a script to adjust AC
string AdjustNaturalAC(int nAdjustment);

//returns a script to add spell to memorized
//does not work for bard/sorcerer, use spell known instead
string AddSpellToMemorized(int nClassPos, int nSpellLevel, int nSlot, int nSpell);

//returns a script to add spell to known
//does not work for divine caster, use spell memorized instead
//also wizard NPCs dont check their spellbooks to change spells
string AddSpellToKnown(int nClassPos, int nSpellLevel, int nSpell);

//returns a script to set a domain
//this does not add/remove the feat associated with any domains
//if nDomainID is -1, the domain is deleted
string SetDomain(int nClassPos, int nDomainNo, int nDomainID);

//returns a script to set spellschool
//does not affect spells already in spellbook
//if nSchool is -1, the school is deleted
string SetSpellSchool(int nClassPos, int nSchool);

//returns a script to remove a known spell
//does not work for divine caster, use spell memorized instead
//also wizard NPCs dont check their spellbooks to change spells
string RemoveSpellFromKnown(int nClassPos, int nSpellLevel, int nSpell);


//returns a script to remove a memorized spell
//does not work for bard/sorcerer, use spell known instead
string RemoveSpellFromMemorized(int nClassPos, int nSpellLevel, int nSlot, int nSpell);

//class
//spell per day
//familiar
//animal companion
//spell redied
//spell metamagic

//constants defined
const int EVENT_SPAWN = 1007;
const int EVENT_DEATH = 1009;
const int EVENT_USER  = 1010;
const int EVENT_BLOCKED = 1012;


string SetCreatureName(string sName, int bLastName = FALSE)
{
//for creatures
//pheonix
//<gff:set 'First' <qq:Sir Brian>>
//unicorn
// /First = qq{Sir Brian};
    string sLoc;
    if(bLastName)
        sLoc = "LastName";
    else
        sLoc = "FirstName";
    return LetoSet(sLoc, sName, "locstring");
}

string SetItemName(string sName)
{
//for items
//phoenix
//<gff:set 'LocalizedName' <qq:Sir Brian>>
//unicorn
// /LocalizedName = qq{Sir Brian};
    return LetoSet("LocalizedName", sName, "locstring");
}

string SetDescription(string sDescription)
{
//phoenix
//<gff:set 'Description' <qq:A mighty warrior of the realm.>>
//unicorn
// /Description = qq{A mighty warrior of the realm.};
    return LetoSet("Description" , sDescription, "locstring");
}

string SetIdentifiedDescription(string sDescription)
{
//phoenix
//<gff:set 'Description' <qq:A mighty warrior of the realm.>>
//unicorn
// /Description = qq{A mighty warrior of the realm.};
    return LetoSet("DescIdentified" , sDescription, "locstring");
}

string SetAbility(int nAbility, int nScore)
{
//phoenix
//<gff:set 'Str' 24>
//unicorn
// /Str = 24;
    string sLoc;
    switch(nAbility)
    {
        case ABILITY_STRENGTH:
            sLoc = "Str";
            break;
        case ABILITY_DEXTERITY:
            sLoc = "Dex";
            break;
        case ABILITY_CONSTITUTION:
            sLoc = "Con";
            break;
        case ABILITY_INTELLIGENCE:
            sLoc = "Int";
            break;
        case ABILITY_WISDOM:
            sLoc = "Wis";
            break;
        case ABILITY_CHARISMA:
            sLoc = "Cha";
            break;
    }
    return LetoSet(sLoc, IntToString(nScore), "byte");
}

string AdjustAbility(int nAbility, int nAdjustment)
{
//phoenix
//<gff:set 'Str' (<gff:get 'Str'>+2)>
//unicorn
// /Str = /Str+2;
    string sAbility;
    switch(nAbility)
    {
        case ABILITY_STRENGTH:
            sAbility= "Str";
            break;
        case ABILITY_DEXTERITY:
            sAbility= "Dex";
            break;
        case ABILITY_CONSTITUTION:
            sAbility= "Con";
            break;
        case ABILITY_INTELLIGENCE:
            sAbility= "Int";
            break;
        case ABILITY_WISDOM:
            sAbility= "Wis";
            break;
        case ABILITY_CHARISMA:
            sAbility= "Cha";
            break;
    }
    return LetoAdjust(sAbility, nAdjustment, "byte");
}

string SetTail(int nTailID)
{
//pheonix
//<gff:add 'Tail' {value=2 setifexists=True}>
//unicorn
// /Tail = 2;
    return LetoSet("Tail", IntToString(nTailID), "byte");
}

string SetWings(int nWingsID)
{
//pheonix
//<gff:add 'Wings' {value=2 setifexists=True}>
//unicorn
// /Wings = 2;
    return LetoSet("Wings", IntToString(nWingsID), "byte");
}

string AdjustSkill(int nSkill, int nAdjustment, int nLevel = 1)
{
//<gff:add 'SkillList/[3]/Rank' {value=<gff:get 'SkillList/[3]/Rank'>+5 setifexists=True}>
//<gff:add 'LvlStatList/[0]/SkillList/[3]/Rank' {value=<gff:get 'LvlStatList/[0]/SkillList/[3]/Rank'>+5 setifexists=True}>
    string sReturn;
    sReturn += LetoAdjust("SkillList/["+IntToString(nSkill)+"]/Rank", nAdjustment, "byte");
    sReturn += LetoAdjust("LvlStatList/["+IntToString(nLevel-1)+"]/SkillList/["+IntToString(nSkill)+"]/Rank", nAdjustment, "byte");
    return sReturn;
}

string SetSkill(int nSkill, int nScore, int nLevel = 1)
{
//<gff:add 'SkillList/[3]/Rank' {value=5 setifexists=True}>
//<gff:add 'LvlStatList/[0]/SkillList/[3]/Rank' {value=5 setifexists=True}>
    string sReturn;
    sReturn += LetoSet("SkillList/["+IntToString(nSkill)+"]/Rank", IntToString(nScore), "byte");
    sReturn += LetoSet("LvlStatList/["+IntToString(nLevel-1)+"]/SkillList/["+IntToString(nSkill)+"]/Rank", IntToString(nScore), "byte");
    return sReturn;
}

string SetSpareSkill(int nScore, int nLevel = 1)
{
//<gff:set 'SkillPoints' 5>
//<gff:set 'LvlStatList/[0]/SkillPoints' 5>
    string sReturn;
    sReturn += LetoSet("SkillPoints", IntToString(nScore), "byte");
    sReturn += LetoSet("LvlStatList/["+IntToString(nLevel-1)+"]/SkillPoints", IntToString(nScore), "byte");
    return sReturn;
}

string AdjustSpareSkill(int nScore, int nLevel = 1)
{
//<gff:set 'SkillPoints' (<gff:get 'SkillPoints'>+5)>
//<gff:set 'LvlStatList/[0]/SkillPoints' (<gff:get 'LvlStatList/[0]/SkillPoints'>+5)>
    string sReturn;
    sReturn += LetoAdjust("SkillPoints", nScore, "word");
    sReturn += LetoAdjust("LvlStatList/["+IntToString(nLevel-1)+"]/SkillPoints", nScore, "word");
    return sReturn;
}

string SetRace(int nRace)
{
//pheonix
//<gff:add 'Race' {value=2 setifexists=True}>
//unicorn
// /Race = 2;
    return LetoSet("Race", IntToString(nRace), "byte");
}

string AdjustHitPoints(int nHP, int nLevel = 1)
{
//<gff:set 'HitPoints' (<HitPoints>+5)>
//<gff:set 'LvlStatList/[0]/LvlStatHitDie' (<LvlStatList/[0]/LvlStatHitDie>+5)>
//<gff:set 'MaxHitPoints' (<MaxHitPoints>+5)>
//<gff:set 'CurrentHitPoints' (<CurrentHitPoints>+5)>
//<gff:set 'PregameCurrent' (<PregameCurrent>+5)>
    string sReturn;
    sReturn += LetoAdjust("HitPoints", nHP, "short");
    sReturn += LetoAdjust("LvlStatList/["+IntToString(nLevel-1)+"]/LvlStatHitDie", nHP, "short");
    sReturn += LetoAdjust("MaxHitPoints", nHP, "short");
    sReturn += LetoAdjust("CurrentHitPoints", nHP, "short");
    sReturn += LetoAdjust("PregameCurrent", nHP, "short");
    return sReturn;
}

string SetGender(int nGender)
{
//pheonix
//<gff:add 'Gender' {value=2 setifexists=True}>
//unicorn
// /Gender = 2;
    return LetoSet("Gender", IntToString(nGender), "byte");
}

string SetSkinColor(int nColor)
{
//pheonix
//<gff:add 'Color_Skin' {value=2 setifexists=True}>
//unicorn
// /Color_Skin = 2;
    return LetoSet("Color_Skin", IntToString(nColor), "byte");
}

string SetHairColor(int nColor)
{
//pheonix
//<gff:add 'Color_Hair' {value=2 setifexists=True}>
//unicorn
// /Color_Hair = 2;
    return LetoSet("Color_Hair", IntToString(nColor), "byte");
}

string SetTatooColor(int nColor, int nTattoo)
{
//pheonix
//<gff:add 'Color_Tattoo1' {value=2 setifexists=True}>
//unicorn
// /Color_Tattoo1 = 2;
    return LetoSet("Color_Tattoo"+IntToString(nTattoo), IntToString(nColor), "byte");
}

string SetMovement(int nRate)
{
//pheonix
//<gff:add 'MovementRate' {value=2 setifexists=True}>
//unicorn
// /MovementRate = 2;
    return LetoSet("MovementRate", IntToString(nRate), "byte");
}

string SetSoundset(int nSoundsetID)
{
//pheonix
//<gff:add 'SoundSetFile' {value=2 setifexists=True}>
//unicorn
// /SoundSetFile = 2;
    return LetoSet("SoundSetFile", IntToString(nSoundsetID), "word");
}

string SetPCPortrait(string sPortrait)
{
//pheonix
//<gff:add 'Portrait' {value='dw_f_01_' setifexists=True}>
//unicorn
// /Portriat = 'dw_f_01_';
    return LetoSet("Portrait", "po_"+sPortrait, "resref");
}

string SetNPCPortrait(int nPortraitID)
{
//pheonix
//<gff:add 'PortraitId' {value='23' setifexists=True}>
//unicorn
// /PortraitId = 23;
    return LetoSet("PortraitId", IntToString(nPortraitID), "word");
}

string SetScript(int nEvent, string sScript)
{
//pheonix
//<gff:add 'ScriptAttacked' {type='resref' value='eras3' setifexists=True}>
//unicorn
// /ScriptAttacked = 'eras3';
    string sEvent = "Script";
    switch(nEvent)
    {
        case EVENT_ATTACKED:
            sEvent += "Attacked";
            break;
        case EVENT_DAMAGED:
            sEvent += "Damaged";
            break;
        case EVENT_DEATH:
            sEvent += "Death";
            break;
        case EVENT_DIALOGUE:
            sEvent += "Dialogue";
            break;
        case EVENT_DISTURBED:
            sEvent += "Disurbed";
            break;
        case EVENT_END_COMBAT_ROUND:
            sEvent += "EndRound";
            break;
        case EVENT_HEARTBEAT:
            sEvent += "Heartbeat";
            break;
        case EVENT_PERCEIVE:
            sEvent += "OnNotice";
            break;
        case EVENT_SPAWN:
            sEvent += "Spawn";
            break;
        case EVENT_SPELL_CAST_AT:
            sEvent += "SpellAt";
            break;
        case EVENT_USER:
            sEvent += "UserDefined";
            break;
        case EVENT_BLOCKED:
            sEvent += "OnBlocked";
            break;
    }
    return LetoSet(sEvent, sScript, "resref");
}

string SetSave(int nSaveType, int nSave)
{
//pheonix
//<gff:add 'willbonus' {type='byte' value='32' setifexists=True}>
//unicorn
// /willbonus = 32;
    string sSaveType;
    switch(nSaveType)
    {
        case SAVING_THROW_FORT:
            sSaveType += "fort";
            break;
        case SAVING_THROW_REFLEX:
            sSaveType += "reflex";
            break;
        case SAVING_THROW_WILL:
            sSaveType += "will";
            break;
    }
    sSaveType += "bonus' ";
    return LetoSet(sSaveType, IntToString(nSave), "byte");
}

string AdjustSave(int nSaveType, int nAdjustment)
{
//<gff:set 'willbonus' (<gff:get 'willbonus'>+2)>
    string sSaveType;
    switch(nSaveType)
    {
        case SAVING_THROW_FORT:
            sSaveType += "fort";
            break;
        case SAVING_THROW_REFLEX:
            sSaveType += "reflex";
            break;
        case SAVING_THROW_WILL:
            sSaveType += "will";
            break;
    }
    sSaveType += "bonus' ";
    return LetoAdjust(sSaveType, nAdjustment, "byte");
}

string SetNaturalAC(int nAC)
{
//pheonix
//<gff:add 'NaturalAC' {value='23' setifexists=True}>
//unicorn
// /NaturalAC = 23;
//this wont work for players
    return LetoSet("NaturalAC", IntToString(nAC), "byte");
}

string AdjustNaturalAC(int nAdjustment)
{
//<gff:set 'NaturalAC' <gff:get 'NaturalA'>+2>
//this wont work for players
    return LetoAdjust("NaturalAC", nAdjustment, "byte");
}

string SetDomain(int nClassPos, int nDomainNo, int nDomainID)
{
//<gff:add 'ClassList/[0]/Domain1'  {type='byte' value='2' setifexists=True}>
//this doesnt alter the matching feats
    return LetoSet("ClassList/["+IntToString(nClassPos-1)+"]/Domain"+IntToString(nDomainID), IntToString(nDomainNo), "byte");
}

string SetSpellSchool(int nClassPos, int nSchool)
{
//<gff:add 'ClassList/[0]/School'  {type='byte' value='2' setifexists=True}>
    return LetoSet("ClassList/["+IntToString(nClassPos-1)+"]/School", IntToString(nSchool), "byte");
}

//THESE FUNCTIONS BELOW DO NOT WORK WITH UNICORN SYNTAX YET

string AddSpellToMemorized(int nClassPos, int nSpellLevel, int nSlot, int nSpell)
{
//<gff:add 'ClassList/[0]/MemorizedList3/[3]/Spell'          {type='word' value='251' setifexists=True}>
//<gff:add 'ClassList/[0]/MemorizedList3/[3]/SpellFlags'     {type='byte' value='0'   setifexists=True}>
//<gff:add 'ClassList/[0]/MemorizedList3/[3]/Ready'          {type='byte' value='0'   setifexists=True}>
//<gff:add 'ClassList/[0]/MemorizedList3/[3]/SpellMetaMagic' {type='byte' value='0'   setifexists=True}>

    string sScript = LetoAdd("ClassList/["+IntToString(nClassPos)+"]/MemorizedList"+IntToString(nSpellLevel)+"/["+IntToString(nSlot)+"]/Spell", IntToString(nSpell), "word");
    sScript       += LetoAdd("ClassList/["+IntToString(nClassPos)+"]/MemorizedList"+IntToString(nSpellLevel)+"/["+IntToString(nSlot)+"]/SpellFlags", IntToString(1), "byte");
    sScript       += LetoAdd("ClassList/["+IntToString(nClassPos)+"]/MemorizedList"+IntToString(nSpellLevel)+"/["+IntToString(nSlot)+"]/Ready", IntToString(1), "byte");
    sScript       += LetoAdd("ClassList/["+IntToString(nClassPos)+"]/MemorizedList"+IntToString(nSpellLevel)+"/["+IntToString(nSlot)+"]/SpellMetaMagic", IntToString(0), "byte");
    return sScript;
}

string AddSpellToKnown(int nClassPos, int nSpellLevel, int nSpell)
{
//<gff:add 'ClassList/[0]/KnownList3/[_]/Spell'          {type='word' value='251' setifexists=True}>
//<gff:add 'ClassList/[0]/KnownList3/[_]/SpellFlags'     {type='byte' value='0'   setifexists=True}>
//<gff:add 'ClassList/[0]/KnownList3/[_]/Ready'          {type='byte' value='0'   setifexists=True}>
//<gff:add 'ClassList/[0]/KnownList3/[_]/SpellMetaMagic' {type='byte' value='0'   setifexists=True}>

    string sScript = LetoAdd("ClassList/["+IntToString(nClassPos)+"]/KnownList"+IntToString(nSpellLevel)+"/Spell", IntToString(nSpell), "word");
    return sScript;
}

//THESE FUNCTIONS BELOW DO NOT WORK WITH UNICORN SYNTAX YET

string RemoveSpellFromMemorized(int nClassPos, int nSpellLevel, int nSlot, int nSpell)
{
//<gff:delete 'ClassList/[0]/MemorizedList3/[3]/Spell'>
//<gff:delete 'ClassList/[0]/MemorizedList3/[3]/SpellFlags'>
//<gff:delete 'ClassList/[0]/MemorizedList3/[3]/Ready'>
//<gff:delete 'ClassList/[0]/MemorizedList3/[3]/SpellMetaMagic'>
    string sScript = "<gff:delete 'ClassList/["+IntToString(nClassPos)+"]/MemorizedList"+IntToString(nSpellLevel)+"/["+IntToString(nSlot)+"]/Spell'>";
    sScript +=       "<gff:delete 'ClassList/["+IntToString(nClassPos)+"]/MemorizedList"+IntToString(nSpellLevel)+"/["+IntToString(nSlot)+"]/SpellFlags'>";
    sScript +=       "<gff:delete 'ClassList/["+IntToString(nClassPos)+"]/MemorizedList"+IntToString(nSpellLevel)+"/["+IntToString(nSlot)+"]/Ready'>";
    sScript +=       "<gff:delete 'ClassList/["+IntToString(nClassPos)+"]/MemorizedList"+IntToString(nSpellLevel)+"/["+IntToString(nSlot)+"]/SpellMetaMagic'>";
    return sScript;
}

string AddFeat(int nFeat, int nLevel = 1)
{
//<gff:add 'FeatList/Feat' 3>
//<gff:add 'LvlStatList/[0]/FeatList/Feat' 3>
    string sReturn = "<gff:add 'Featlist/Feat' ";
    sReturn += IntToString(nFeat)+ ">";
    sReturn += "<gff:add 'LvlStatList/["+IntToString(nLevel-1)+"]/Featlist/Feat' ";
    sReturn += IntToString(nFeat)+ ">";
    return sReturn;
}

string RemoveSpellFromKnown(int nClassPos, int nSpellLevel, int nSpell)
{
//<gff:replace {name='ClassList/[1]/KnownList2' value=25 DeleteParent}>
    string sScript = "<gff:replace {name='ClassList/["+IntToString(nClassPos)+"]/KnownList"+IntToString(nSpellLevel)+"' value=25 DeleteParent}>";
    return sScript;
}

string RemoveFeat(int nFeat)
{
//<gff:replace {name='Feat' value=25 DeleteParent}>
    string sReturn = "<gff:replace {name='Feat' value="+IntToString(nFeat);
    sReturn += " DeleteParent=true}>";
    return sReturn;
}

//credit to demux
string AddSpecialAbility(int iSpell = -1, int iAmount = 1, int iLevel = 1)
{
//<gff:add 'SpecAbilityList' {type='list'}>
//"<gff:add 'SpecAbilityList/Spell' {type='word' value=5}>";
//"<gff:add 'SpecAbilityList/[_]/SpellFlags' {type='byte' value=1}>";
//"<gff:add 'SpecAbilityList/[_]/SpellCasterLevel' {type='byte' value=3}>";

    if(iSpell < 0 || iLevel < 0 || iAmount < 1) return "";

    string script = "";
    int i;
    string sSpell = IntToString(iSpell);
    string sAmount = IntToString(iAmount);
    string sLevel = IntToString(iLevel);

    PrintString("Adding spell... Name: "+sSpell+" | Amount: "+sAmount+" | Level: "+sLevel);
    for(i=0; i < iAmount; i++) {
        script +=
            "<gff:add 'SpecAbilityList' {type='list'}>"+
            "<gff:add 'SpecAbilityList/Spell' {type='word' value="+sSpell+"}>"+
            "<gff:add 'SpecAbilityList/[_]/SpellFlags' {type='byte' value=1}>"+
            "<gff:add 'SpecAbilityList/[_]/SpellCasterLevel' {type='byte' value="+sLevel+"}>";
    }

    return script;
}

//void main(){}



Whew, now I have been able to get the stat modifiers (like STR, CON, DEX, etc) to work perfectly. The problem now is getting the HP modifier to work along with adding feats.

Is the AddFeat function just messed up? Can someone enlighten to me as to what the level parameter does?

Thanks so much and sorry about all of the questions.[/code]
Back to top
View user's profile Send private message
ShaDoOoW



Joined: 20 Aug 2005
Posts: 584

PostPosted: Tue Dec 04, 2007 22:35    Post subject: Reply with quote

Well, you can add feat without Letoscript, so why do letoscript function for it?
And you certainly know letoscript disadvantiges.

So if you don't know how to add feat ingame.

You need:
1. Creature Hide item in palette. (No properties)
2. Know resref of this item.

Step 1 installation:
As far as I tested, game unequip this hide from INVENTORY_SLOT_CARMOUR slot every time the player log-in. Maybe also destroy it, if it is possible,
1) So set this item to Plot.
2) In OnPlayerEnter re-equip this item to INVENTORY_SLOT_CARMOUR slot. (If this item doesn't exist, create it and then equip it)
3) I had some problems with equipping, so I created new function ActionForceEquipItem based on PRC's one(but IMO better than original), that repaired it.

Step 2 adding feat:
1) To add a feat, add an BonusFeat itemproperty to Hide.

Step 3 adding new bonus feat:
1) Get a iprp_feats.2da, and add new feat according to bioware's lines.

Code:

//Equip item until it is in nInventorySlot
void ActionForceEquipItem(object oItem, int nInventorySlot);

//returns TRUE if the item is in nInventorySlot, FALSE otherwise
int GetIsInSlot(int nInventorySlot, object oItem, object oCreature=OBJECT_SELF);

int GetIsInSlot(int nInventorySlot, object oItem, object oCreature=OBJECT_SELF)
{
return GetItemInSlot(nInventorySlot,oCreature)==oItem;
}

void ActionForceEquipItemContinue(object oItem, int nInventorySlot)
{
object oSelf = OBJECT_SELF;
 if(GetIsObjectValid(oSelf) && GetIsObjectValid(oItem))
 {
  if(!GetIdentified(oItem))
  {
  SetIdentified(oItem,TRUE);
  }
  if(!GetIsInSlot(nInventorySlot,oItem,oSelf))
  {
   if(GetLocalObject(oSelf,"ActionForceEquipItem_"+IntToString(nInventorySlot))==oItem)
   {
   ClearAllActions();
   ActionEquipItem(oItem,nInventorySlot);
   DelayCommand(0.1,ActionForceEquipItemContinue(oItem,nInventorySlot));
   }
  }
  else
  {
  DeleteLocalInt(oItem,"FIRST_TIME");
  DeleteLocalInt(oItem,"ActionForceEquipItem");
  DeleteLocalObject(oSelf,"ActionForceEquipItem_"+IntToString(nInventorySlot));
  }
 }
}

void ActionForceEquipItem(object oItem, int nInventorySlot)
{
 if(!GetLocalInt(oItem,"ActionForceEquipItem"))
 {
 SetLocalObject(OBJECT_SELF,"ActionForceEquipItem_"+IntToString(nInventorySlot),oItem);
 SetLocalInt(oItem,"ActionForceEquipItem",TRUE);
 ActionForceEquipItemContinue(oItem,nInventorySlot);
 }
}

_________________
Community Patch / NWNX Patch / NWNX Files / NWNX Connect
Back to top
View user's profile Send private message
william_hunter



Joined: 31 Jan 2007
Posts: 149

PostPosted: Wed Dec 05, 2007 1:42    Post subject: Reply with quote

If your systems already use hides that won't work though. Only one hide per character. Thats the reason I use Letoscripting. I have subraces assigned by hides.
_________________
The Realm of Tharagon NWN PW
Back to top
View user's profile Send private message
ShaDoOoW



Joined: 20 Aug 2005
Posts: 584

PostPosted: Wed Dec 05, 2007 16:15    Post subject: Reply with quote

I'm not sure I understand, but if you already have Hide for subrace's purposes, you can skip most of my steps and add bonus feat item property on this Hide, don't you?
_________________
Community Patch / NWNX Patch / NWNX Files / NWNX Connect
Back to top
View user's profile Send private message
william_hunter



Joined: 31 Jan 2007
Posts: 149

PostPosted: Thu Dec 06, 2007 22:51    Post subject: Reply with quote

That requires modification of the hide on an individual basis, doesn't it? I think the greatest benefit to Letoscripting is that you can do the edit directly on a character file, and still use a hide for other, less likely to change, things.


I'm not saying the hide method isn't good, I am sort of defending Letoscripting because I am comfortable using it and really like it.
_________________
The Realm of Tharagon NWN PW
Back to top
View user's profile Send private message
ShaDoOoW



Joined: 20 Aug 2005
Posts: 584

PostPosted: Fri Dec 07, 2007 0:12    Post subject: Reply with quote

Of course, If you using some public racial system from vault, it could be problem. I don't like this systems and I prefer own ones.
_________________
Community Patch / NWNX Patch / NWNX Files / NWNX Connect
Back to top
View user's profile Send private message
Zunath



Joined: 06 Jul 2006
Posts: 183

PostPosted: Thu Dec 13, 2007 21:59    Post subject: Reply with quote

I'd really prefer to use letoscripting to add the feats but if I need to, I'll use the hides.

I have a question about them though: Can I add properties to the hide later on if I need to? How do I get it? Just a simple GetItemPossessedBy?
Back to top
View user's profile Send private message
ShaDoOoW



Joined: 20 Aug 2005
Posts: 584

PostPosted: Fri Dec 14, 2007 21:30    Post subject: Reply with quote

Well that should work too. But there is issue, that every log-in hide is unequipped and destroyed. So you must create copy when the hide is unequipped.

Note: I'm using hide as also as the player ID.

Code:

 object oItem = GetPCItemLastUnequipped();
 object oPC = GetPCItemLastUnequippedBy();
 string sTag = GetTag(oItem);
  if(GetResRef(oItem)=="id_sablona")
  {
  object id = CopyItem(oItem,oPC,TRUE);
  //DebugInt("unequip id",GetIsObjectValid(oPC));
  }


But in this moment is not possible equip the new one. At least my function ActionForceEquip failed there. So I equipping it in function returning hide object. And first usage of this function is in OnClientEnter event so when PC log in, all new feats are in the place Smile .

Code:
object GetPlayerID(object oPlayer)
{
object ID = GetItemInSlot(INVENTORY_SLOT_CARMOUR,oPlayer);
 if(GetIsObjectValid(ID))
 {
 return ID;
 }
ID = GetFirstItemInInventory(oPlayer);
 while(GetIsObjectValid(ID))
 {
  if(GetResRef(ID)=="id_sablona")
  {
  AssignCommand(oPlayer,ActionForceEquipItem(ID,INVENTORY_SLOT_CARMOUR));
  return ID;
  }
 ID = GetNextItemInInventory(oPlayer);
 }
return ID;
}

Need functions posted above.


Btw what letoscript version have you got? I recommend 4.0.6.27 RC 3, maybe I you don't have it, that you got same bug as me: look this link for my posts
_________________
Community Patch / NWNX Patch / NWNX Files / NWNX Connect
Back to top
View user's profile Send private message
FunkySwerve



Joined: 02 Jun 2005
Posts: 377

PostPosted: Sat Dec 15, 2007 3:51    Post subject: Reply with quote

Once 1.69 goes live you'll no longer need letoscript. One of our scripters has built a plugin that allows the edits to be made in memory, with no booting, called NWNeXalt. Link to the forums:

http://highergroundpoa.proboards3.com/index.cgi?board=nwnxhax

When 1.69 goes live a public release will follow.

Funky
Back to top
View user's profile Send private message
ShaDoOoW



Joined: 20 Aug 2005
Posts: 584

PostPosted: Sat Dec 15, 2007 12:44    Post subject: Reply with quote

WOW, awesome. But will it work under windows?
_________________
Community Patch / NWNX Patch / NWNX Files / NWNX Connect
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    nwnx.org Forum Index -> Scripts and Modules All times are GMT + 2 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group