RATDOG/_module/nss/ra_st_nature.nss
Jaysyn904 4b6d20bbc2 Module update.
More NPCs & stores spawning instead of placed.  Door scripts added.  Change all random commoners & nobles over to X2 AI scripts.
2021-09-06 01:12:39 -04:00

286 lines
10 KiB
Plaintext

//::////////////////////////////////////////////////////////////////////////////
//:: Store Open Script
//:: ra_st_nature
//:: 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);
}