#include "inc_system_const" #include "inc_helper_funcs" #include "colors_inc" #include "nwnx_funcs_l" //////////////////////////////////////////////////////////////////////////////////////////////// // Main include file for the REO inventory system. // // // // This set of script will limit the number of items a player can carry to a specified value. // // You can also increase or decrease this limit if you want. // // The idea is to mimic the Resident Evil games' inventory system. Players must choose what // // items to bring and can't run around with an endless supply of ammo, for example. // // Note that this currently only works for Linux operating systems and it requires NWNX to // // be functional. The nwnx_funcs plugin is also required. // // // // Created by Zunath on 7/21/2011 // //////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////// // SYSTEM CONFIGURATION // ////////////////////////// // The initial inventory limit. All players have at least this number of item slots. // Default: 15 const int INV_BASE_INVENTORY_LIMIT = 15; // This number should be changed to reflect the number of "system items" in players' inventories. // This means if you have items that players cannot get rid of (Cursed items) then you need to increase this number. // Typically servers have one item to store information on, and perhaps a few others for DMFI, SimTools, etc. const int INV_NUMBER_SYSTEM_ITEMS = 4; ///////////////////// // SYSTEM MESSAGES // ///////////////////// const string INV_MESSAGE_INVENTORY_FULL = "Your inventory is full!"; //////////////// // PROTOTYPES // //////////////// // Returns the number of inventory slots a player has. // oPC = The player object // bBonuses = If set TRUE, this will return the base inventory slot amount PLUS the player's bonus slots count // If set FALSE, it returns only the base inventory slot amount (INV_BASE_INVENTORY_LIMIT). // Returns -1 on error. int INV_GetPlayerInventoryLimit(object oPC, int bBonuses = TRUE); // Returns TRUE if oItem is exempt from inventory rules. // Returns FALSE if oItem is NOT exempt from inventory rules. // This means that even if this item is acquired, it will not count towards the PC's item limit. int INV_IsItemExempt(object oItem); // Call this on your module's OnItemAcquired event. // It will handle adding an item to a player's inventory limit, if applicable. // If there's not enough room, the item is copied back to its source and an error message is displayed. void INV_OnModuleAcquire(); /////////////// // FUNCTIONS // /////////////// int INV_GetPlayerInventoryLimit(object oPC, int bBonuses = TRUE) { if(!GetIsPC(oPC)) return -1; object oDatabase = GetItemPossessedBy(oPC, PC_DATABASE); int iBonus = GetLocalInt(oDatabase, INV_INVENTORY_BONUS); int iSlots = INV_BASE_INVENTORY_LIMIT; if(bBonuses) iSlots = iSlots + iBonus; return iSlots; } void INV_SetPlayerInventoryLimit(object oPC, int iNewLimit) { // Only works for PCs, and only if the new limit is at least 0 if(!GetIsPC(oPC) || iNewLimit < 0) return; object oDatabase = GetItemPossessedBy(oPC, PC_DATABASE); int iLimit = iNewLimit + INV_BASE_INVENTORY_LIMIT; SetLocalInt(oDatabase, INV_INVENTORY_BONUS, iNewLimit); SendMessageToPC(oPC, ColorTokenGray() + "Your inventory limit is now " + ColorTokenGreen() + IntToString(iLimit) + ColorTokenGray() + " items." + ColorTokenEnd()); } int INV_IsItemExempt(object oItem) { string sResref = GetResRef(oItem); string sTag = GetTag(oItem); string sName = GetName(oItem); // Specific items if(sResref == PC_DATABASE || // Database item sResref == "dmfi_dicebag" || // DMFI Dicebag sResref == "dmfi_pc_emote" || // DMFI PC Emote Wand sResref == "fky_chat_target" || // SimTools Command Targeter sResref == "firearm_magazine" || // Combat system firearm magazine sResref == "e_gun_mag" || // Combat system enhanced firearm magazine sResref == "i_gun_mag" || // Combat system incendiary firearm magazine sResref == "nw_it_gold001" || // Gold sResref == "rhs_furn_tool" || // Furniture Tool sResref == "" || // Item doesn't have a resref GetLocalInt(oItem, "ZEP_CR_TEMPITEM") || // CEP Crafting System - Prevents a bug when PC tries to craft armor appearance on full inventory sName == "PC Properties") // Patch 1.69 PC properties skin. Can't get the tag of this for whatever reason so I use its name. return TRUE; // Key items else if(GetStringLeft(sTag, 8) == "KEYITEM_") return TRUE; else return FALSE; } void INV_OnModuleAcquire() { object oPC = GetModuleItemAcquiredBy(); // When an item is created on the inventory of a player, the inventory system should not // fire. Otherwise the item could drop to the ground or the server may crash. // This enables players to possibly go beyond their item limit, but for the sake of convenience // I think this is okay. if(GetLocalInt(oPC, "INV_PREVENT_SYSTEM_FROM_FIRING") == TRUE) return; object oItem = GetModuleItemAcquired(); object oPreviousOwner = GetModuleItemAcquiredFrom(); string sResref = GetResRef(oItem); // Non-PCs and DMs don't fire this script. // Neither do exempt items. if(!GetIsPC(oPC) || GetIsDM(oPC) || INV_IsItemExempt(oItem)) return; // Offset the count by the number of "system items". // I.E: Items that don't count towards the limit. int iNumberItems = GetItemCount(oPC) - INV_NUMBER_SYSTEM_ITEMS; int iLimit = INV_GetPlayerInventoryLimit(oPC); // Check inventory limit against current item count if(iNumberItems > iLimit) { SendMessageToPC(oPC, ColorTokenRed() + INV_MESSAGE_INVENTORY_FULL + ColorTokenEnd()); // If the previous owner is invalid, then the item came from the ground. Simply create the item // at oPC's feet. if(oPreviousOwner == OBJECT_INVALID) { // CopyObject doesn't have the option to copy variables, so we're forced to // copy all variables from the original item to the copy. It's a pain in the // ass, but there's no alternative. object oCopy = CopyObject(oItem, GetLocation(oPC)); CopyVariables(oItem, oCopy); } else { CopyItem(oItem, oPreviousOwner, TRUE); } DestroyObject(oItem); } // There's room - keep it and update the player's inventory status else { string sColor; // If player has reached maximum, display in red. // Otherwise display in gray. if(iNumberItems >= iLimit) sColor = ColorTokenRed(); else sColor = ColorTokenGray(); SendMessageToPC(oPC, ColorTokenGray() + "Inventory: " + IntToString(iNumberItems) + " / " + IntToString(iLimit) + ColorTokenEnd()); } } // Error checking void main(){}