//:://////////////////////////////////////////////////////////////////////////// //:: Store Open Script //:: ra_st_temple //:: For slightly faster store restocking //:: -DM Heatstroke //:://////////////////////////////////////////////////////////////////////////// /* This script will allow stores to partially reset themselves to their original state after some time has passed. Intended for persistent worlds. */ //:://////////////////////////////////////////////////////////////////////////// //:: Created By: The Krit //:: Created On: 3/2/07 //:: Replaces the "do-nothing" BioWare script. //:://////////////////////////////////////////////////////////////////////////// //:://////////////////////////////////////////////////////////////////////////// // // This script will cause a store's finite inventory // and limited gold to be (partially) replenished // after a certain amount of time passes. It will also // clean out new items and excess gold. I call this // restocking. // // The timer starts when the store is first opened // after server rest or the last restock. The time // is random, but will be at least RESTOCK_TIME_FIXED // real-time hours. The random component of the time // is added to this minimum, and will range from 0 // to RESTOCK_TIME_VARIABLE minutes. // // Items are only replaced if all of that type have // been sold (and not bought back). The chance for an // item to be replaced is RESTOCK_CHANCE. // // Items not in the store's original inventory have a // chance to be removed (sold to unspecified NPC's, if // you will) when the store restocks. This chance is // UNSTOCK_CHANCE. // // After the store restocks, the store's gold supply -- if // limited -- will be no more than GOLD_MAX_FRACTION times // its starting value. // // After the store restocks, the store's gold supply -- if // limited -- will be no less than GOLD_MIN_FRACTION times // its starting value. // // If you try to mess with things and make GOLD_MAX_FRACTION // less than GOLD_MIN_FRACTION, you deserve whatever happens. // You may also smack yourself for making trouble. :) // //:://////////////////////////////////////////////////////////////////////////// // // The variables mentioned above are set globally below. // In addition, you can change the value for a particular // store by setting a local variable of the same name // (and type) on the store. // NOTE: These variables must be set on the *store*, not // the merchant. // //:://////////////////////////////////////////////////////////////////////////// // // This script will (likely) break if you switch a // store from unlimited gold to limited gold through // scripting. Don't do that. There would be no // original gold level to refer to when restocking. // //:://////////////////////////////////////////////////////////////////////////// // The following is the minimum number of real-time (not // game-time) hours that elapse before a store gets // restocked. const int RESTOCK_TIME_FIXED = 2; // The following is the maximum number of minutes (not // hours) that a restock might be delayed beyond the // above minimum number of hours. const int RESTOCK_TIME_VARIABLE = 30; // The following is the chance (percentage) that a depleted // item will be replaced when the restocking occurs. Each // item rolls this percentage individually. const int RESTOCK_CHANCE = 75; // The following is the chance (percentage) that an item // not in the store's original inventory will be removed // when a restocking occurs. const int UNSTOCK_CHANCE = 5; // The following is the fraction (floating point) of the // stores original gold that is the most a store can have // after restocking. // (No effect on stores with unlimited gold.) const float GOLD_MAX_FRACTION = 2.20; // The following is the fraction (floating point) of the // stores original gold that is the least a store can have // after restocking. // (No effect on stores with unlimited gold.) const float GOLD_MIN_FRACTION = 0.80; // The following are names of local variables used by // this script. const string STORE_GOLD = "TK_STORE_STARTING_GOLD"; const string ORIG_INVENTORY = "TK_STORE_STARTING_INVENTORY_"; const string CUR_INVENTORY = "TK_STORE_CURRENT_INVENTORY_"; const string INVENTORY_STACK = "TK_STORE_INVENTORY_STACK_LIST_"; const string INVENTORY_LIST = "TK_STORE_INVENTORY_LIST_"; const string INVENTORY_SIZE = "TK_STORE_INVENTORY_SIZE"; const string INVENTORIED = "TK_STORE_DID_INVENTORY"; const string RESTOCK_ORDERED = "TK_STORE_DID_DELAY"; // Records the store's current (starting) inventory. void DoInventory(); // Restocks the store. void Restock(); ////////////////////////////////////////////////// // main() // // Intended for a store's OnOpenStore event, replacing the BioWare default. // void main() { // See if the store's original inventory has been recorded. if ( !GetLocalInt(OBJECT_SELF, INVENTORIED) ) { // Record the current inventory. DoInventory(); SetLocalInt(OBJECT_SELF, INVENTORIED, TRUE); } // See if a restock is currently on delay. if ( !GetLocalInt(OBJECT_SELF, RESTOCK_ORDERED) ) { // Determine the restock times (possibly stored locally). int nRestockHours = GetLocalInt(OBJECT_SELF, "RESTOCK_TIME_FIXED"); if ( nRestockHours == 0 ) nRestockHours = RESTOCK_TIME_FIXED; int nRestockMinutes = GetLocalInt(OBJECT_SELF, "RESTOCK_TIME_VARIABLE"); if ( nRestockMinutes == 0 ) nRestockMinutes = RESTOCK_TIME_VARIABLE; // Order (delay) a restock. DelayCommand( TurnsToSeconds(60*nRestockHours + Random(nRestockMinutes+1)), Restock()); SetLocalInt(OBJECT_SELF, RESTOCK_ORDERED, TRUE); } } ////////////////////////////////////////////////// // DoInventory() // // Records the store's current (starting) inventory. // void DoInventory() { // Record the store's current gold. SetLocalInt(OBJECT_SELF, STORE_GOLD, GetStoreGold(OBJECT_SELF)); // Record the store's current inventory. int nCount = 0; object oItem = GetFirstItemInInventory(); while ( oItem != OBJECT_INVALID ) { // We are only concerned with items in finite supply. if ( !GetInfiniteFlag(oItem) ) { string sResRef = GetResRef(oItem); // Set a boolean flag based on the blueprint name. SetLocalInt(OBJECT_SELF, ORIG_INVENTORY + sResRef, TRUE); // Add sResRef to the list of blueprints. SetLocalString(OBJECT_SELF, INVENTORY_LIST + IntToString(nCount), sResRef); // Record the stack size. SetLocalInt(OBJECT_SELF, INVENTORY_STACK + IntToString(nCount), GetItemStackSize(oItem)); // Update the count. nCount++; } // Next item. oItem = GetNextItemInInventory(); } // Record the length of the list of blueprints. SetLocalInt(OBJECT_SELF, INVENTORY_SIZE, nCount); } ////////////////////////////////////////////////// // Restock() // // Restocks the store. // void Restock() { // Check the store's gold. int nCurGold = GetStoreGold(OBJECT_SELF); // We are only concerned if the store has limited gold. if ( nCurGold > -1 ) { // Determine the min and max gold fractions (possibly stored locally). float fGoldMin = GetLocalFloat(OBJECT_SELF, "GOLD_MIN_FRACTION"); if ( fGoldMin == 0.0 ) fGoldMin = GOLD_MIN_FRACTION; float fGoldMax = GetLocalFloat(OBJECT_SELF, "GOLD_MAX_FRACTION"); if ( fGoldMax == 0.0 ) fGoldMax = GOLD_MAX_FRACTION; // Calculate the minimum and maximum gold levels. int nOrigGold = GetLocalInt(OBJECT_SELF, STORE_GOLD); int nMinGold = FloatToInt(IntToFloat(nOrigGold) * fGoldMin); int nMaxGold = FloatToInt(IntToFloat(nOrigGold) * fGoldMax); // Check for too little gold. if ( nCurGold < nMinGold ) SetStoreGold(OBJECT_SELF, nMinGold); // Check for too much gold. else if ( nCurGold > nMaxGold ) SetStoreGold(OBJECT_SELF, nMaxGold); } // Determine the unstock chance (possibly stored locally). int nUnstockChance = GetLocalInt(OBJECT_SELF, "UNSTOCK_CHANCE"); if ( nUnstockChance == 0 ) nUnstockChance = UNSTOCK_CHANCE; // Scan the store's current inventory. // Record which original items are still around. // Possibly remove non-original items. object oItem = GetFirstItemInInventory(); while ( oItem != OBJECT_INVALID ) { // We are only concerned with items in finite supply. if ( !GetInfiniteFlag(oItem) ) { string sResRef = GetResRef(oItem); // See if this item is an original item. if ( GetLocalInt(OBJECT_SELF, ORIG_INVENTORY + sResRef) ) { // Set a boolean flag (temporarily) based on the blueprint name. SetLocalInt(OBJECT_SELF, CUR_INVENTORY + sResRef, TRUE); DelayCommand(0.0, DeleteLocalInt(OBJECT_SELF, CUR_INVENTORY + sResRef)); } // See if this (not original) item should be removed. else if ( d100() <= nUnstockChance ) // Delete this item. DestroyObject(oItem); } // Next item. oItem = GetNextItemInInventory(); } // Determine the restock chance (possibly stored locally). int nRestockChance = GetLocalInt(OBJECT_SELF, "RESTOCK_CHANCE"); if ( nRestockChance == 0 ) nRestockChance = RESTOCK_CHANCE; // Loop through the list of items that might be restored. int nCount = GetLocalInt(OBJECT_SELF, INVENTORY_SIZE); while ( nCount-- > 0 ) { string sResRef = GetLocalString(OBJECT_SELF, INVENTORY_LIST + IntToString(nCount)); // Make sure no items of this type are in the store's inventory (before this loop). if ( !GetLocalInt(OBJECT_SELF, CUR_INVENTORY + sResRef) ) // See if this item should be restocked. if ( d100() <= nRestockChance ) // Add this item to the store. CreateItemOnObject(sResRef, OBJECT_SELF, GetLocalInt(OBJECT_SELF, INVENTORY_STACK + IntToString(nCount))); } // Restocking is no longer in progress. SetLocalInt(OBJECT_SELF, RESTOCK_ORDERED, FALSE); }