#include "inc_array" #include "inc_array_b" #include "aps_include" //takes a hex string "0x####" and returns the integer base 10 equivalent //Full credit to Axe Murderer int HexToInt( string sHex); int HexToInt( string sHex) { if( sHex == "") return 0; if( GetStringLeft( sHex, 2) == "0x") sHex = GetStringRight( sHex, GetStringLength( sHex) -2); while( GetStringLength( sHex) > 8) sHex = GetStringRight( sHex, GetStringLength( sHex) -1); string sConvert = "0123456789ABCDEF"; int iMult = 1; int iIntVal = 0; while( sHex != "") { string sDigit = GetStringRight( sHex, 1); sHex = GetStringLeft( sHex, GetStringLength( sHex) -1); int iPos = FindSubString( sConvert, sDigit); if( (iPos >= 0) && (iPos <= 15)) iIntVal += (iPos *iMult); else return 0; iMult *= 16; } return iIntVal; } /* Credit to He Who Watches taken from the Homebrew Functions sticky on the bioware scripting forum This version stores the local strings on a different waypoint object for each 2da file. It requires you to define a waypoint with tag "CACHEWP", and to place one instance of that waypoint somewhere in your module (preferable in a location unviewable by players). If it is not present, the cache wil be created at the module start. Also, this version will use NWNX database characteristics to provide a more persistant cache across reboots. It is assumed that reading local strings on waypoints is faster than DB access, but this has not been tested. */ string GetDB2DA(string datafile, string column, int row) { string sSQL = "SELECT "+column+" FROM " +datafile + " WHERE RowNo='" + IntToString(row)+"'"; SQLExecDirect(sSQL); if (SQLFirstRow() == SQL_SUCCESS) return SQLGetData(1); else return ""; } void Put2DAInDB(string datafile, string column, int row, string s) { string sSQL = "SELECT "+column+" FROM " +datafile + " WHERE RowNo='" + IntToString(row)+"'"; SQLExecDirect(sSQL); if (SQLFirstRow() == SQL_SUCCESS) { //replace existing data (probably wont ever happen, but you never know!) sSQL = "UPDATE "+datafile+" SET "+column+"='"+s+"' WHERE RowNo='"+IntToString(row)+"'"; SQLExecDirect(sSQL); } else { //not in DB already //update an exisitng row sSQL = "UPDATE "+datafile+" SET "+column+"='"+s+"' WHERE RowNo='"+IntToString(row)+"'"; SQLExecDirect(sSQL); //check updating it worked sSQL = "SELECT "+column+" FROM " +datafile + " WHERE RowNo='" + IntToString(row)+"'"; SQLExecDirect(sSQL); if (SQLFirstRow() == SQL_SUCCESS) return; //try adding a new row sSQL = "INSERT INTO "+datafile+" ("+column+", RowNo) VALUES ('"+s+"', '"+IntToString(row)+"')"; SQLExecDirect(sSQL); //check adding it worked sSQL = "SELECT "+column+" FROM " +datafile + " WHERE RowNo='" + IntToString(row)+"'"; SQLExecDirect(sSQL); if (SQLFirstRow() == SQL_SUCCESS) return; //try adding a new column sSQL = "ALTER TABLE "+datafile+" ADD "+column+" varchar(255)"; SQLExecDirect(sSQL); //attempt to update the new column sSQL = "UPDATE "+datafile+" SET "+column+"='"+s+"' WHERE RowNo='"+IntToString(row)+"'"; SQLExecDirect(sSQL); //check adding it worked sSQL = "SELECT "+column+" FROM " +datafile + " WHERE RowNo='" + IntToString(row)+"'"; SQLExecDirect(sSQL); if (SQLFirstRow() == SQL_SUCCESS) return; //if update didnt work, add a new row sSQL = "INSERT INTO "+datafile+" ("+column+", RowNo) VALUES ('"+s+"', '"+IntToString(row)+"')"; SQLExecDirect(sSQL); //check adding it worked sSQL = "SELECT "+column+" FROM " +datafile + " WHERE RowNo='" + IntToString(row)+"'"; SQLExecDirect(sSQL); if (SQLFirstRow() == SQL_SUCCESS) return; //now we have tried updating, adding a new row, adding a new colum //so we have to add a new table sSQL = "CREATE TABLE "+datafile+" ("+column+" varchar(255), RowNo varchar(255), PRIMARY KEY(RowNo))"; SQLExecDirect(sSQL); sSQL = "INSERT INTO "+datafile+" ("+column+", RowNo) VALUES ('"+s+"', '"+IntToString(row)+"')"; SQLExecDirect(sSQL); //check adding it worked sSQL = "SELECT "+column+" FROM " +datafile + " WHERE RowNo='" + IntToString(row)+"'"; SQLExecDirect(sSQL); if (SQLFirstRow() == SQL_SUCCESS) return; //if we get here then there has to be a db problem // DoDebug("Problem adding to DB. datafile="+datafile+", column="+column+", row="+IntToString(row)+", s="+s); } } //wrapper for bioware Get2daString function //caches the result on waypoints //also uses the database for cross-reboot persistant caching //Original by He Who Watches //Modified by Primogenitor string Get2DACache(string datafile, string column, int row, int cachenull = TRUE, int debug = FALSE); string Get2DACache(string datafile, string column, int row, int cachenull = TRUE, int debug = FALSE) { object cachewp = GetObjectByTag("CACHEWP"); location lCache = GetLocation(cachewp); if (!GetIsObjectValid(cachewp)) lCache = GetStartingLocation(); string filewpname = "CACHED_"+GetStringUpperCase(datafile)+"_"+GetStringUpperCase(column)+"_"+IntToString(row/1000); object filewp = GetObjectByTag(filewpname); if (!GetIsObjectValid(filewp)) { filewp = CreateObject(OBJECT_TYPE_WAYPOINT,"NW_WAYPOINT001",lCache,FALSE,filewpname); } string s = GetLocalString(filewp, "2DA_"+datafile+"_"+column+"_"+IntToString(row)); if (s == "") { //now check db s = GetDB2DA(datafile, column, row); if(s=="") { s = Get2DAString(datafile, column, row); if (cachenull&&(s == "")) { if (debug) SendMessageToAllDMs("Null value (****) or error opening "+datafile+".2da (row "+IntToString(row)+", column "+column+"), my tag: "+GetTag(OBJECT_SELF)); s = "****"; } } if (s!="") SetLocalString(filewp, "2DA_"+datafile+"_"+column+"_"+IntToString(row), s); if (s!="") Put2DAInDB(datafile, column, row, s); } if (s=="****") return ""; else return s; } // returns true if given an allowable alignment // returns false otherwise // // example // GetIsValidAlignment (ALIGNMENT_CHAOTIC, ALIGNMENT_GOOD, 21, 3, 0 ); // should return false // // Credit to Joe Travel int GetIsValidAlignment( int iLawChaos, int iGoodEvil, int iAlignRestrict, int iAlignRstrctType, int iInvertRestriction ); int GetIsValidAlignment ( int iLawChaos, int iGoodEvil,int iAlignRestrict, int iAlignRstrctType, int iInvertRestriction ) { //deal with no restrictions first if(iAlignRstrctType == 0) return TRUE; //convert the ALIGNMENT_* into powers of 2 iLawChaos = FloatToInt(pow(2.0, IntToFloat(iLawChaos-1))); iGoodEvil = FloatToInt(pow(2.0, IntToFloat(iGoodEvil-1))); //initialise result varaibles int iAlignTest, iRetVal = TRUE; //do different test depending on what type of restriction if(iAlignRstrctType == 1 || iAlignRstrctType == 3) //I.e its 1 or 3 iAlignTest = iLawChaos; if(iAlignRstrctType == 2 || iAlignRstrctType == 3) //I.e its 2 or 3 iAlignTest = iAlignTest | iGoodEvil; //now the real test. if(iAlignRestrict & iAlignTest)//bitwise AND comparison iRetVal = FALSE; //invert it if applicable if(iInvertRestriction) iRetVal = !iRetVal; //and return the result return iRetVal; } //circular random location getter // by Mixcoatl // download from // http://nwvault.ign.com/Files/scripts/data/1065075424375.shtml location GetRandomLocation(location lBase, float fDistance=1.0); location GetRandomLocation(location lBase, float fDistance=1.0) { // Pick a random angle for the location. float fAngle = IntToFloat(Random(3600)) / 10.0; // Pick a random facing for the location. float fFacing = IntToFloat(Random(3600)) / 10.0; // Pick a random distance from the base location. float fHowFar = IntToFloat(Random(FloatToInt(fDistance * 10.0))) / 10.0; // Retreive the position vector from the location. vector vPosition = GetPositionFromLocation(lBase); // Modify the base x/y position by the distance and angle. vPosition.y += (sin(fAngle) * fHowFar); vPosition.x += (cos(fAngle) * fHowFar); // Return the new random location. return Location(GetAreaFromLocation(lBase), vPosition, fFacing); } //wrapper for setcustomtoken //sets a local on self equal to token void SetToken(int nCustomTokenNumber, string sTokenValue); void SetToken(int nCustomTokenNumber, string sTokenValue) { SetCustomToken(nCustomTokenNumber, sTokenValue); SetLocalString(OBJECT_SELF, "TOKEN"+IntToString(nCustomTokenNumber), sTokenValue); } //this returns the cost to get to a score //or the cost saved by dropping from that score int GetCost(int nAbilityScore) { if(nAbilityScore >18) return -1; int nCost = (nAbilityScore-11)/2; if(nCost < 1) nCost = 1; return nCost; }