Files
Anphillia_PRC8/_module/nss/socket_inc.nss
Jaysyn904 28cdb617b3 Initial commit
Adding all of the current content for Anphillia Unlimited.
2024-01-04 07:49:38 -05:00

474 lines
16 KiB
Plaintext

/************************************************************************
* script name : socket_inc
* created by : eyesolated
* date : 2019/3/21
*
* description : Central include script for Socketing
*
* changes : 2019/3/21 - eyesolated - Initial creation
************************************************************************/
#include "socket_cfg"
#include "ip_inc"
#include "util_inc"
#include "nwnx_itemprop"
#include "prc_misc_const"
/*******************************************************************************
* FUNCTION DECLARATION
******************************************************************************/
// Creates the database tables used for Socketing
void socket_CreateTables();
// Returns FALSE if any of the required Socketing Tables is missing
int socket_GetTablesExist();
// Drops all Socketing Tables
void socket_DropTables();
// Adds information about a socketable item to the database
void socket_AddSocketableItem(string sResRef, int nItemCategory, int nItemProperty, int nItemSubProperty = -1);
// Returns the resref of a socketable item
string socket_GetSocketableItem();
// Retrieves socket information for sSocket
// Return Values: Socket does not exist - RETURN.* will be "" / 0 / OBJECT_INVALID depending on variable type
// Socket is empty - RETURN.Item_Socketed_ResRef will be SOCKET_SOCKETED_NONE
// Socketed - RETURN will hold all information
struct SOCKET_STRUCT_SOCKET_INFO socket_GetSocketInfo(object oItem, int nSocket = 1);
// Get the first empty socket of oItem
// Returns -1 if there is no empty socket available
int socket_GetEmptySocket(object oItem);
// Retrieves the itemproperty associated with oSocketableItem if socketed in oItem
itemproperty socket_GetProperty(object oItem, object oSocketableItem);
// Returns the Item Category (SOCKET_ITEMCATEGORY_*)
int socket_GetItemCategory(object oItem);
// (re)Sets the Description of oItem to include Socket information
void socket_SetDescription(object oItem);
// Inserts oItemToSocket into oItem and informs oPC about the result
// Returns TRUE on success, FALSE on failure
int socket_InsertSocketableItem(object oPC, object oItem, object oItemToSocket);
// Creates a new socket in the given position
// Returns FALSE if the socket couldn't be created, TRUE if it was created successfully
int socket_CreateSocket(object oItem, int nSocket = 1);
// Tries to create nCount Sockets in oItem (Maximum of 3).
// Returns the nubmer of new sockets created.
int socket_CreateSockets(object oItem, int nCount);
/*******************************************************************************
* FUNCTION IMPLEMENTATION
******************************************************************************/
int socket_GetTablesExist()
{
int nExists_Base = NWNX_SQL_ExecuteQuery("DESCRIBE " + SOCKET_TABLE_BASE);
return (nExists_Base);
}
void socket_DropTables()
{
NWNX_SQL_ExecuteQuery("DROP TABLE " + SOCKET_TABLE_BASE);
}
void socket_CreateTables()
{
// Base Table
string Table_Base = SOCKET_TABLE_BASE + " (" +
"ResRef varchar(16) NOT NULL," +
"ItemCategory int NOT NULL," +
"ItemProperty_ID int NOT NULL," +
"ItemSubProperty_ID int NOT NULL DEFAULT -1" +
")";
NWNX_SQL_ExecuteQuery("CREATE TABLE IF NOT EXISTS " + Table_Base);
}
void socket_AddSocketableItem(string sResRef, int nItemCategory, int nItemProperty, int nItemSubProperty = -1)
{
string sSQL = "INSERT INTO " + SOCKET_TABLE_BASE + " (ResRef, ItemCategory, ItemProperty_ID, ItemSubProperty_ID) ";
sSQL += "VALUES (?, ?, ?, ?)";
NWNX_SQL_PrepareQuery(sSQL);
NWNX_SQL_PreparedString(0, sResRef);
NWNX_SQL_PreparedInt(1, nItemCategory);
NWNX_SQL_PreparedInt(2, nItemProperty);
NWNX_SQL_PreparedInt(3, nItemSubProperty);
NWNX_SQL_ExecutePreparedQuery();
}
string socket_GetSocketableItem()
{
string sSQL = "SELECT DISCTINCT ResRef FROM " + SOCKET_TABLE_BASE + " ORDER BY RAND() LIMIT 1";
NWNX_SQL_ExecuteQuery(sSQL);
if (NWNX_SQL_ReadyToReadNextRow())
{
NWNX_SQL_ReadNextRow();
return NWNX_SQL_ReadDataInActiveRow(0);
}
return "";
}
struct SOCKET_STRUCT_SOCKET_INFO socket_GetSocketInfo(object oItem, int nSocket = 1)
{
struct SOCKET_STRUCT_SOCKET_INFO SocketInfo;
SocketInfo.Item_Socketed_ResRef = GetLocalString(oItem, SOCKET_VAR_SOCKET_RESREF + "_" + IntToString(nSocket));
// If there is no ResRef or is an empty socket, return right away
if (SocketInfo.Item_Socketed_ResRef == "" ||
SocketInfo.Item_Socketed_ResRef == SOCKET_SOCKETED_NONE)
return SocketInfo;
// Read the other variables
SocketInfo.Item_Socketed_Tag = GetLocalString(oItem, SOCKET_VAR_SOCKET_TAG + "_" + IntToString(nSocket));
SocketInfo.Item_Socketed_Name = GetLocalString(oItem, SOCKET_VAR_SOCKET_NAME + "_" + IntToString(nSocket));
return SocketInfo;
}
int socket_GetEmptySocket(object oItem)
{
int nSocket;
string ResRef;
for (nSocket = 1; nSocket <= SOCKET_MAXIMUM; nSocket++)
{
ResRef = GetLocalString(oItem, SOCKET_VAR_SOCKET_RESREF + "_" + IntToString(nSocket));
if (ResRef == "")
return -1;
else if (ResRef == SOCKET_SOCKETED_NONE)
return nSocket;
}
return -1;
}
itemproperty socket_GetProperty(object oItem, object oSocketableItem)
{
itemproperty Result;
int nItemCategory = socket_GetItemCategory(oItem);
if (nItemCategory == SOCKET_ITEMCATEGORY_UNKNOWN)
return Result;
string sItemToSocket_ResRef = GetResRef(oSocketableItem);
string sQuery;
sQuery = "SELECT A.ItemSubProperty_ID" +
", B." +CS_IP_ID +
", B." + CS_IP_VARONE +
", B." + CS_IP_VARTWO +
", B." + CS_IP_VARTHREE +
" FROM " + SOCKET_TABLE_BASE + " A" +
" JOIN " + CS_IP_TABLE + " B ON A.ItemProperty_ID = B." + CS_IP_ID +
" WHERE A.ResRef = ? AND (A.ItemCategory & ?) != 0 AND B." + CS_IP_LEVEL + " = ?";
NWNX_SQL_PrepareQuery(sQuery);
NWNX_SQL_PreparedString(0, sItemToSocket_ResRef);
NWNX_SQL_PreparedInt(1, nItemCategory);
NWNX_SQL_PreparedInt(2, GetLocalInt(oSocketableItem, SOCKET_VAR_ITEM_LEVEL));
NWNX_SQL_ExecutePreparedQuery();
if (NWNX_SQL_ReadyToReadNextRow())
{
NWNX_SQL_ReadNextRow();
int IP_SubProperty = StringToInt(NWNX_SQL_ReadDataInActiveRow(0));
int IP_ID = StringToInt(NWNX_SQL_ReadDataInActiveRow(1));
int IP_VarOne = StringToInt(NWNX_SQL_ReadDataInActiveRow(2));
int IP_VarTwo = StringToInt(NWNX_SQL_ReadDataInActiveRow(3));
int IP_VarThree = StringToInt(NWNX_SQL_ReadDataInActiveRow(4));
struct STRUCT_IP_PropertyDetails ip = ip_GetSpecificProperty(GetBaseItemType(oSocketableItem), IP_ID, IP_VarOne, IP_VarTwo, IP_VarThree);
Result = ip.IP;
// Force specific Property if there is one
if (IP_SubProperty != -1)
{
struct NWNX_IPUnpacked IPU = NWNX_ItemProperty_UnpackIP(Result);
IPU.nSubType = IP_SubProperty;
Result = NWNX_ItemProperty_PackIP(IPU);
}
}
else
{
WriteTimestampedLogEntry("SOCKET: Failed to retrieve DB values for [" + sItemToSocket_ResRef + "]");
}
return Result;
}
int socket_GetItemCategory(object oItem)
{
int nBaseItemType = GetBaseItemType(oItem);
switch (nBaseItemType)
{
case BASE_ITEM_AMULET: return SOCKET_ITEMCATEGORY_JEWELRY_AMULET;
case BASE_ITEM_ARMOR: return SOCKET_ITEMCATEGORY_ARMOR;
case BASE_ITEM_BELT: return SOCKET_ITEMCATEGORY_BELT;
case BASE_ITEM_BOOTS: return SOCKET_ITEMCATEGORY_BOOTS;
case BASE_ITEM_BRACER:
case BASE_ITEM_BRACER_SHIELD: return SOCKET_ITEMCATEGORY_BRACERS;
case BASE_ITEM_CLOAK: return SOCKET_ITEMCATEGORY_CLOAK;
case BASE_ITEM_GLOVES: return SOCKET_ITEMCATEGORY_GLOVES;
case BASE_ITEM_HELMET: return SOCKET_ITEMCATEGORY_HELMET;
case BASE_ITEM_RING: return SOCKET_ITEMCATEGORY_JEWELRY_RING;
case BASE_ITEM_SMALLSHIELD:
case BASE_ITEM_LARGESHIELD:
case BASE_ITEM_TOWERSHIELD: return SOCKET_ITEMCATEGORY_SHIELD;
case BASE_ITEM_LIGHTCROSSBOW:
case BASE_ITEM_HEAVYCROSSBOW: return SOCKET_ITEMCATEGORY_RANGED_CROSSBOW;
case BASE_ITEM_SHORTBOW:
case BASE_ITEM_LONGBOW: return SOCKET_ITEMCATEGORY_RANGED_BOW;
case BASE_ITEM_SHORTSWORD:
case BASE_ITEM_LONGSWORD:
case BASE_ITEM_BATTLEAXE:
case BASE_ITEM_BASTARDSWORD:
case BASE_ITEM_LIGHTFLAIL:
case BASE_ITEM_WARHAMMER:
case BASE_ITEM_LIGHTMACE:
case BASE_ITEM_HALBERD:
case BASE_ITEM_TWOBLADEDSWORD:
case BASE_ITEM_GREATSWORD:
case BASE_ITEM_GREATAXE:
case BASE_ITEM_DAGGER:
case BASE_ITEM_CLUB:
case BASE_ITEM_DART:
case BASE_ITEM_DIREMACE:
case BASE_ITEM_DOUBLEAXE:
case BASE_ITEM_HEAVYFLAIL:
case BASE_ITEM_LIGHTHAMMER:
case BASE_ITEM_HANDAXE:
case BASE_ITEM_KAMA:
case BASE_ITEM_KATANA:
case BASE_ITEM_KUKRI:
case BASE_ITEM_MORNINGSTAR:
case BASE_ITEM_QUARTERSTAFF:
case BASE_ITEM_RAPIER:
case BASE_ITEM_SCYTHE:
case BASE_ITEM_SHORTSPEAR:
case BASE_ITEM_SHURIKEN:
case BASE_ITEM_SICKLE:
case BASE_ITEM_SCIMITAR:
case BASE_ITEM_SLING:
case BASE_ITEM_DWARVENWARAXE:
case BASE_ITEM_WHIP:
case BASE_ITEM_GRENADE:
case BASE_ITEM_TRIDENT:
case BASE_ITEM_THROWINGAXE:
case BASE_ITEM_CSLASHWEAPON:
case BASE_ITEM_CPIERCWEAPON:
case BASE_ITEM_CBLUDGWEAPON:
case BASE_ITEM_CSLSHPRCWEAP:
//:: PRC Weapons
case BASE_ITEM_LIGHT_LANCE:
case BASE_ITEM_HEAVY_PICK:
case BASE_ITEM_LIGHT_PICK:
case BASE_ITEM_SAI:
case BASE_ITEM_NUNCHAKU:
case BASE_ITEM_FALCHION:
case BASE_ITEM_SAP:
case BASE_ITEM_KATAR:
case BASE_ITEM_HEAVY_MACE:
case BASE_ITEM_MAUL:
case BASE_ITEM_DOUBLE_SCIMITAR:
case BASE_ITEM_GOAD:
case BASE_ITEM_EAGLE_CLAW:
case BASE_ITEM_ELVEN_LIGHTBLADE:
case BASE_ITEM_ELVEN_THINBLADE:
case BASE_ITEM_ELVEN_COURTBLADE:
// CEP weapons:
case 300: // trident_1h
case 301: // heavypick
case 302: // lightpick
case 303: // sai
case 304: // nunchaku
case 305: // falchion
case 308: // sap
case 309: // daggerassn
case 310: // katar
case 312: // lightmace2
case 313: // kukri2
case 316: // falchion_2
case 317: // heavy_mace
case 318: // maul
case 319: // mercurial_longsword
case 320: // mercurial_greatsword
case 321: // scimitar_double
case 322: // goad
case 323: // windfirewheel
case 324: // maugdoublesword
case 327: // Flowers_Crystal
case 329: // tool_2handed
case 330: // Longsword_2
return SOCKET_ITEMCATEGORY_MELEE;
}
return SOCKET_ITEMCATEGORY_UNKNOWN;
}
void socket_SetDescription(object oItem)
{
string sSaved = GetLocalString(oItem, SOCKET_VAR_ITEM_DESCRIPTION);
string sDescription = GetDescription(oItem);
string sSocketDescription = "\n";
int n;
struct SOCKET_STRUCT_SOCKET_INFO socketInfo;
for (n = 1; n <= SOCKET_MAXIMUM; n++)
{
socketInfo = socket_GetSocketInfo(oItem, n);
if (socketInfo.Item_Socketed_ResRef == "")
break;
else if (socketInfo.Item_Socketed_ResRef == SOCKET_SOCKETED_NONE)
sSocketDescription += "\n" + SOCKET_DESCRIPTION_SOCKET + SOCKET_DESCRIPTION_SOCKET_EMPTY;
else
sSocketDescription += "\n" + SOCKET_DESCRIPTION_SOCKET + GetLocalString(oItem, SOCKET_VAR_SOCKET_NAME + "_" + IntToString(n));
}
// If there is no socket description, return right away
if (sSocketDescription == "\n")
return;
// If saved is empty or the retrieved description shows no signs of socketing texts,
// save the "original/pre-Socketing" description and append sSocketDescription
if (sSaved == "" ||
FindSubString(sDescription, SOCKET_DESCRIPTION_SOCKET) == -1)
{
SetLocalString(oItem, SOCKET_VAR_ITEM_DESCRIPTION, sDescription);
sDescription += sSocketDescription;
}
// otherwise, use the saved "original/pre-Socketing" description and append there
else
sDescription = sSaved + sSocketDescription;
SetDescription(oItem, sDescription);
}
int socket_InsertSocketableItem(object oPC, object oItem, object oItemToSocket)
{
string sItemToSocket_ResRef = GetResRef(oItemToSocket);
// If this is the Socket Creator, create a socket
if (GetIsDM(oPC) &&
sItemToSocket_ResRef == "socket_creator")
{
socket_CreateSockets(oItem, 1);
return FALSE;
}
string sItemToSocket_Name = GetName(oItemToSocket);
// Find out if there's an empty socket
int nSocket = socket_GetEmptySocket(oItem);
if (nSocket == -1)
{
SendMessageToPC(oPC, "There is no empty socket available on " + GetName(oItem));
return FALSE;
}
else
{
// Find out if this item is already socketed
int n = 1;
while (n < nSocket)
{
if (GetLocalString(oItem, SOCKET_VAR_SOCKET_RESREF + "_" + IntToString(n)) == sItemToSocket_ResRef)
{
SendMessageToPC(oPC, "A socket already contains " + sItemToSocket_Name);
return FALSE;
}
n++;
}
}
// Retrieve information about the socketed item from Database
itemproperty IP = socket_GetProperty(oItem, oItemToSocket);
if (!GetIsItemPropertyValid(IP))
return FALSE;
// Add the identified item property to the item
IPSafeAddItemProperty(oItem, IP, 0.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING);
// Set the local strings for the sockets on the item
SetLocalString(oItem, SOCKET_VAR_SOCKET_RESREF + "_" + IntToString(nSocket), sItemToSocket_ResRef);
SetLocalString(oItem, SOCKET_VAR_SOCKET_TAG + "_" + IntToString(nSocket), GetTag(oItemToSocket));
SetLocalString(oItem, SOCKET_VAR_SOCKET_NAME + "_" + IntToString(nSocket), sItemToSocket_Name);
// Destory the now socketed item
DestroyObject(oItemToSocket);
// Set the new description
socket_SetDescription(oItem);
// Tell the player he successfully socketed the item
SendMessageToPC(oPC, "You successfully socketed " + sItemToSocket_Name + " into " + GetName(oItem));
return TRUE;
}
int socket_CreateSocket(object oItem, int nSocket = 1)
{
// Only items of known Categories are able to get Sockets
if (socket_GetItemCategory(oItem) == SOCKET_ITEMCATEGORY_UNKNOWN)
return FALSE;
string sExisting = GetLocalString(oItem, SOCKET_VAR_SOCKET_RESREF + "_" + IntToString(nSocket));
// If the Socket already exists, return FALSE
if (sExisting != "")
return FALSE;
else
{
SetLocalString(oItem, SOCKET_VAR_SOCKET_RESREF + "_" + IntToString(nSocket), SOCKET_SOCKETED_NONE);
return TRUE;
}
}
int socket_CreateSockets(object oItem, int nCount)
{
// Only items of known Categories are able to get Sockets
if (socket_GetItemCategory(oItem) == SOCKET_ITEMCATEGORY_UNKNOWN)
return FALSE;
// Reduce nCount if needed
if (nCount > SOCKET_MAXIMUM)
nCount = SOCKET_MAXIMUM;
int nCreated = 0;
int n;
for (n = 1; n <= SOCKET_MAXIMUM; n++)
{
if (socket_CreateSocket(oItem, n))
nCreated++;
if (nCreated == nCount)
break;
}
if (nCreated > 0)
socket_SetDescription(oItem);
return nCreated;
}
void socket_CreateSocketableItem(object oTarget, int nLevel = -1)
{
// Select an item
string sResRef = socket_GetSocketableItem();
// Create selected item in oTarget's inventory
object oItem = CreateItemOnObject(sResRef, oTarget);
// Set Name of item (recoloring based on level/rarity
// Set level on item
SetLocalInt(oItem, SOCKET_VAR_ITEM_LEVEL, nLevel);
}