763 lines
24 KiB
Plaintext
763 lines
24 KiB
Plaintext
//::///////////////////////////////////////////////
|
|
//:: XP2 Disposeable Treasure System
|
|
//:: x2_inc_treasure
|
|
//:: Copyright (c) 2003 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By: Georg Zoeller
|
|
//:: Created On: 2003-06-03
|
|
//:://////////////////////////////////////////////
|
|
//#include "prc_x2_itemprop"
|
|
#include "prc_x2_itemprop"
|
|
|
|
const int X2_DTS_CLASS_LOW = 0; //Treasure Class Low
|
|
const int X2_DTS_CLASS_MEDIUM = 1; //Treasure Clas Medium
|
|
const int X2_DTS_CLASS_HIGH = 2; //Treasure Class High
|
|
|
|
const int X2_DTS_TYPE_DISP =1;
|
|
const int X2_DTS_TYPE_AMMO=2;
|
|
const int X2_DTS_TYPE_GOLD=4; // actually gold and gems
|
|
const int X2_DTS_TYPE_ITEM=8; // char specific Item
|
|
|
|
|
|
// These are the system default values
|
|
const int X2_DTS_BASECHANCE_TREAS = 50;// Basic chance for treasure
|
|
const int X2_DTS_MAXITEMS = 2;
|
|
const int X2_DTS_STACKVAR = 50; // Stack variation is 50-100 percent of the number listed in the 2da
|
|
|
|
// These are the names of the default 2das.
|
|
const string X2_DTS_2DA_DISP = "des_treas_disp"; // 2da for disposeable class treasure
|
|
const string X2_DTS_2DA_AMMO = "des_treas_ammo"; // 2da for ammo class treasure
|
|
const string X2_DTS_2DA_GOLD = "des_treas_gold"; // 2da for gold n gems
|
|
const string X2_DTS_2DA_ITEM = "des_treas_items"; // 2da for specific items
|
|
|
|
const string X2_DTS_2DA_ENHANCEMENTS = "des_treas_enh";
|
|
|
|
const string X2_DTS_2DA_CONF = "des_conf_treas"; // 2da with configuration
|
|
|
|
// *** P R O T O T Y P E S ***
|
|
|
|
|
|
// Generate random, disposeable treasure on the container
|
|
// oContainer - Valid object with inventory
|
|
// oOpener - The one who opened the container
|
|
// nClass - Treasure Class (X2_DTS_CLASS_*)
|
|
// nType - Treasure Type (X2_DTS_TYPE_*), default = X2_DTS_TYPE_DISPOSEABLE | X2_DTS_TYPE_GOLD
|
|
// Values: X2_DTS_TYPE_DISPOSEABLE - Potions, Kits, etc
|
|
// X2_DTS_TYPE_AMMO - Ammunition
|
|
// X2_DTS_TYPE_GOLD - Gold and Gems
|
|
// X2_DTS_TYPE_ITEM - Character Optimized treasure (ignores treasure class)
|
|
// Example:
|
|
// Generate Low Class Ammo and Gold+Gems
|
|
// DTSGenerateTreasureOnContainer (oChest, X2_DTS_CLASS_LOW, X2_DTS_TYPE_AMMO | X2_DTS_TYPE_GOLD);
|
|
void DTSGenerateTreasureOnContainer (object oContainer, object oOpener, int nClass, int nType = 5);
|
|
|
|
// Generates one random, character specific item on container
|
|
// Treasure is optimized to suit a characters needs
|
|
// if bIgnoreFeats is set TRUE, the system will not use Feats (i.e. Weapon Focus)
|
|
// to determine a baseitem to spawn
|
|
object DTSGenerateCharSpecificTreasure (object oContainer, object oAdventurer, int bIgnoreFeats = FALSE);
|
|
|
|
|
|
// Initializes the treasure system by loading x2_conf_tras.2da
|
|
// nConfigIndex - RowIndex of the configuration to load
|
|
void DTSInitialize( int nConfigIndex = 0);
|
|
|
|
// Sets the area wide chance for treasure Generation ...
|
|
// if bDisable = TRUE, then no random treasure is generated at all
|
|
void DTSSetAreaTreasureProbability(object oArea, int nBaseChance, int bDisabled = FALSE);
|
|
|
|
// Enchantes the weapon passed in oItem with a scaled enhancement bonus
|
|
// nLevel should be the level of the player who is going to receive
|
|
// the item. Lookup is done via des_treas_enh.2da.
|
|
// returns TRUE on success
|
|
int DTSGrantCharSpecificWeaponEnhancement(int nLevel, object oItem);
|
|
|
|
|
|
// *** I M P L E M E N T A T I O N ***
|
|
|
|
|
|
/* ----------------------------------------------------------
|
|
Private Functions - Do not call from outside
|
|
---------------------------------------------------------- */
|
|
|
|
void DTSDebug(string s)
|
|
{
|
|
//SendMessageToPC(GetFirstPC(),"***DTS-Debug: " +s);
|
|
WriteTimestampedLogEntry("***DTS-Debug: " +s);
|
|
}
|
|
|
|
|
|
// Get a 2da String or the supplied default if string is empty
|
|
string DTSGet2DAStringOrDefault(string s2DA, string sColumn, int nRow, string sDefault)
|
|
{
|
|
string sRet;
|
|
sRet =Get2DAString(s2DA, sColumn, nRow);
|
|
if (sRet == "****" || sRet == "")
|
|
{
|
|
sRet = sDefault;
|
|
}
|
|
return sRet;
|
|
|
|
}
|
|
|
|
// Maps the X2_DTS_TYPE_* value given in nType to a 2da name
|
|
string DTSGet2DANameByType(int nType)
|
|
{
|
|
string sLookUp;
|
|
string sDefault;
|
|
if (nType == X2_DTS_TYPE_DISP)
|
|
{
|
|
sLookUp = "X2_DTS_2DA_DISP";
|
|
sDefault = X2_DTS_2DA_DISP;
|
|
}
|
|
else if (nType == X2_DTS_TYPE_AMMO)
|
|
{
|
|
sLookUp = "X2_DTS_2DA_AMMO";
|
|
sDefault = X2_DTS_2DA_AMMO;
|
|
}
|
|
|
|
else if (nType == X2_DTS_TYPE_ITEM)
|
|
{
|
|
sLookUp = "X2_DTS_2DA_ITEM";
|
|
sDefault = X2_DTS_2DA_ITEM;
|
|
}
|
|
else
|
|
{
|
|
sLookUp = "X2_DTS_2DA_GOLD";
|
|
sDefault = X2_DTS_2DA_GOLD;
|
|
}
|
|
|
|
string sRet = GetLocalString(GetModule(),sLookUp);
|
|
if (sRet == "")
|
|
{
|
|
sRet = sDefault;
|
|
}
|
|
return sRet;
|
|
|
|
}
|
|
|
|
// Maps the X2_DTS_CLASS_* value given in nType to row name in the 2da
|
|
string DTSGet2DAColNameByClass(int nClass)
|
|
{
|
|
if (nClass == X2_DTS_CLASS_MEDIUM)
|
|
return "TMed";
|
|
else if (nClass == X2_DTS_CLASS_HIGH)
|
|
return "THigh";
|
|
// if (nClass == X2_DTS_CLASS_LOW)
|
|
// Default to low
|
|
return "TLow";
|
|
}
|
|
|
|
// Returns the number of entries available for random treasure of a given type and class
|
|
// nType - X2_DTS_TYPE_*
|
|
// nClass - X2_DTS_CLASS_* (default = X2_DTS_CLASS_LOW)
|
|
// sCol - used when X2_DTS_TYPE_ITEM is specified
|
|
int DTSGetNoOfRowsInTreasureTable(int nType, int nClass = 1, string sCol = "")
|
|
{
|
|
string s2DA = DTSGet2DANameByType(nType);
|
|
int nRet;
|
|
if (nType == X2_DTS_TYPE_ITEM)
|
|
{
|
|
nRet = StringToInt(Get2DAString(s2DA ,sCol,0));
|
|
}
|
|
else
|
|
{
|
|
string sColName = DTSGet2DAColNameByClass(nClass);
|
|
nRet =GetLocalInt(GetModule(),"X2_DTS_CACHE_"+s2DA+sColName);
|
|
if (nRet !=0)
|
|
{
|
|
return nRet;
|
|
}
|
|
// Row 0 always holds the total number of entries.
|
|
nRet = StringToInt(Get2DAString(s2DA,sColName,0));
|
|
SetLocalInt(GetModule(),"X2_DTS_CACHE_"+s2DA+sColName,nRet);
|
|
}
|
|
return nRet;
|
|
}
|
|
|
|
|
|
int DTSGetBaseChance(object oArea)
|
|
{
|
|
|
|
// Check for override on area
|
|
int nChance = GetLocalInt(oArea,"X2_DTS_BASECHANCE");
|
|
if (nChance == 0) //check configuration
|
|
{
|
|
nChance = GetLocalInt(GetModule(),"X2_DTS_BASECHANCE");
|
|
if (nChance == 0) //take default
|
|
{
|
|
//DTSDebug("++WARNING++ not initialized, using defaults");
|
|
nChance = X2_DTS_BASECHANCE_TREAS;
|
|
}
|
|
else if (nChance == -1) // -1 = no treasure
|
|
nChance = 0;
|
|
}
|
|
else if (nChance == -1) // -1 = no treasure
|
|
nChance = 0;
|
|
return nChance;
|
|
}
|
|
|
|
// Returns the maximum number of items to generate according to the configuration
|
|
// If no configuration is used, default is X2_DTS_MAXITEMS (2)
|
|
int DTSGetMaxItems()
|
|
{
|
|
int nItems= GetLocalInt(GetModule(),"X2_DTS_MAXITEMS");
|
|
if (nItems == 0)
|
|
{
|
|
//DTSDebug("++WARNING++ not initialized, using defaults");
|
|
nItems = X2_DTS_MAXITEMS;
|
|
}
|
|
return nItems;
|
|
}
|
|
|
|
// Returns the stack variation to use when generation stacked items
|
|
// If no configuration is used, default is X2_DTS_STACKVAR (0.5)
|
|
// Stacks are calculated (Stack* X2_DTS_STACKVAR) + Random (Stack *X2_DTS_STACKVAR)
|
|
float DTSGetStackVariation()
|
|
{
|
|
float fStackV = GetLocalFloat(GetModule(),"X2_DTS_STACKVAR");
|
|
if (fStackV == 0.0f)
|
|
{
|
|
//DTSDebug("++WARNING++ not initialized, using defaults");
|
|
fStackV =X2_DTS_STACKVAR / 100.0f;
|
|
}
|
|
return fStackV;
|
|
}
|
|
|
|
// Enchantes the weapon passed in oItem with a scaled enhancement bonus
|
|
// nLevel should be the level of the player who is going to receive
|
|
// the item. Lookup is done via des_treas_enh.2da.
|
|
// returns TRUE on success
|
|
int DTSGrantCharSpecificWeaponEnhancement(int nLevel, object oItem)
|
|
{
|
|
if (! IPGetIsRangedWeapon(oItem) && !IPGetIsMeleeWeapon(oItem))
|
|
{
|
|
return FALSE;
|
|
}
|
|
//int nBT = GetBaseItemType(oItem);
|
|
// RangedWeapon column != 0 we assume its a ranged weapon
|
|
|
|
int bRanged = IPGetIsRangedWeapon(oItem);
|
|
string sCol;
|
|
if (bRanged)
|
|
{
|
|
sCol = "Ranged" ;
|
|
}
|
|
else
|
|
{
|
|
sCol = "Melee";
|
|
}
|
|
|
|
int nBonus = StringToInt(Get2DAString(X2_DTS_2DA_ENHANCEMENTS,sCol, nLevel));
|
|
// remove existing enhancement properties from weapon
|
|
|
|
itemproperty ip = GetFirstItemProperty(oItem);
|
|
while (GetIsItemPropertyValid(ip))
|
|
{
|
|
if (GetItemPropertyType(ip) == ITEM_PROPERTY_ENHANCEMENT_BONUS)
|
|
{
|
|
RemoveItemProperty (oItem,ip);
|
|
}
|
|
ip = GetNextItemProperty(oItem);
|
|
}
|
|
|
|
if (nBonus > 0 && nBonus < 21)
|
|
{
|
|
ip = ItemPropertyEnhancementBonus(nBonus);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT,ip,oItem);
|
|
return TRUE;
|
|
}
|
|
//else
|
|
//{
|
|
// DTSDebug("x2_inc_treasure()::DTSGrantCharSpecificWeaponEnhancement() - invalid bonus generated: " + IntToString(nBonus));
|
|
//}
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
//This is a wrapper for CreateItemOnObject which can handle the stack number
|
|
//given on
|
|
object DTSCreateItemOnObject(string sItemTemplate, object oTarget)
|
|
{
|
|
if (sItemTemplate == "")
|
|
return OBJECT_INVALID;
|
|
int nStack = FindSubString(sItemTemplate,":");
|
|
int nStackSize =1 ;
|
|
object oItem;
|
|
if (nStack>0)
|
|
{
|
|
string sNum = GetSubString(sItemTemplate,nStack+1,GetStringLength(sItemTemplate)-nStack);
|
|
sItemTemplate = GetSubString(sItemTemplate,0,nStack);
|
|
int nMaxStackSize = StringToInt(sNum);
|
|
|
|
// Random part of stacksize
|
|
int nRandom = FloatToInt(DTSGetStackVariation() * nMaxStackSize);
|
|
// fixed part of stacksize
|
|
int nStackSize = nMaxStackSize - nRandom;
|
|
nStackSize +=Random(nRandom);
|
|
|
|
oItem = CreateItemOnObject(sItemTemplate,oTarget,nStackSize);
|
|
}
|
|
else
|
|
{
|
|
oItem = CreateItemOnObject(sItemTemplate,oTarget);
|
|
}
|
|
//if (oItem == OBJECT_INVALID)
|
|
//{
|
|
// DTSDebug(" +++2da ERROR +++ Invalid Entry:" + sItemTemplate);
|
|
//}
|
|
return oItem;
|
|
}
|
|
|
|
|
|
// Returns a single random item resref from the approriate 2da
|
|
// nType - X2_DTS_TYPE_* - Type of Treasure (i.e. disposeable, ammo)
|
|
// nClass - X2_DTS_CLASS_* - Class of Treasure (i.e. high, medium, low)
|
|
string DTSGetRandomItemResRef(int nType, int nClass)
|
|
{
|
|
string s2DA = DTSGet2DANameByType(nType);
|
|
|
|
string sRowName = DTSGet2DAColNameByClass(nClass);
|
|
|
|
// Retrieve the number of items in treasure table
|
|
int nMax = DTSGetNoOfRowsInTreasureTable(nType,nClass);
|
|
if (nMax == 0)
|
|
return "";
|
|
int nRand = Random(nMax)+1; // select a row from 1.. nMax
|
|
string sRet = Get2DAString(s2DA,sRowName,nRand);
|
|
|
|
return sRet;
|
|
}
|
|
|
|
|
|
string DTSGetFeatSpecificItemResRef(int nFeatID)
|
|
{
|
|
string sCol = Get2DAString("des_feat2item","TreasureCol",nFeatID);
|
|
int nRand =DTSGetNoOfRowsInTreasureTable(X2_DTS_TYPE_ITEM,1,sCol);
|
|
nRand = Random(nRand)+1;
|
|
string sItem = Get2DAString(DTSGet2DANameByType(X2_DTS_TYPE_ITEM),sCol,nRand);
|
|
return sItem;
|
|
}
|
|
|
|
|
|
|
|
|
|
// Returns the Highest class of a creature
|
|
int DTSGetHighestClass(object oCreature)
|
|
{
|
|
int nClass1 = GetLevelByPosition(1, oCreature);
|
|
int nClass2 = GetLevelByPosition(2, oCreature);
|
|
int nClass3 = GetLevelByPosition(3, oCreature);
|
|
int nClass4 = GetLevelByPosition(4, oCreature);
|
|
int nClass5 = GetLevelByPosition(5, oCreature);
|
|
int nClass6 = GetLevelByPosition(6, oCreature);
|
|
int nClass7 = GetLevelByPosition(7, oCreature);
|
|
int nClass8 = GetLevelByPosition(8, oCreature);
|
|
|
|
int nHighestClass = 1;
|
|
int nHighestLevel = nClass1;
|
|
|
|
if (nClass2 > nHighestLevel)
|
|
{
|
|
nHighestLevel = nClass2;
|
|
nHighestClass = 2;
|
|
}
|
|
if (nClass3 > nHighestLevel)
|
|
{
|
|
nHighestLevel = nClass3;
|
|
nHighestClass = 3;
|
|
}
|
|
if (nClass4 > nHighestLevel)
|
|
{
|
|
nHighestLevel = nClass4;
|
|
nHighestClass = 4;
|
|
}
|
|
if (nClass5 > nHighestLevel)
|
|
{
|
|
nHighestLevel = nClass5;
|
|
nHighestClass = 5;
|
|
}
|
|
if (nClass6 > nHighestLevel)
|
|
{
|
|
nHighestLevel = nClass6;
|
|
nHighestClass = 6;
|
|
}
|
|
if (nClass7 > nHighestLevel)
|
|
{
|
|
nHighestLevel = nClass7;
|
|
nHighestClass = 7;
|
|
}
|
|
if (nClass8 > nHighestLevel)
|
|
{
|
|
nHighestLevel = nClass8;
|
|
nHighestClass = 8;
|
|
}
|
|
|
|
return GetClassByPosition(nHighestClass, oCreature);
|
|
}
|
|
|
|
|
|
// Returns the FEAT_ID of the feat to use for treasure generation
|
|
//
|
|
// This code tries to figure out what kind of weapon a player would want to use
|
|
// it will examine the players feats in the following order
|
|
//
|
|
// 1. Weapon Master: Weapon of Choise
|
|
// 2. Fighter: Weapon Specialication
|
|
// 3. All: Improved Critical
|
|
// 4. All: Weapon Focus
|
|
// 5. Highest class (will map to class specific feats like FEAT_WEAPON_PROFICIENCY_WIZARD)
|
|
//
|
|
// if you specify bUseNoFeats to be TRUE, the system will decide which item table to use
|
|
// based on the characters class alone (skipping step 1-4). Useful for generating things
|
|
// that are not weapons
|
|
|
|
int DTSDetermineFeatToUse(object oAdventurer, int bDontUseFeats = FALSE)
|
|
{
|
|
//Ok this is not the most beautiful code, but it works since 2da row indices
|
|
//are not allowed to change...
|
|
int nRangeStart;
|
|
int nRangeStop;
|
|
int i;
|
|
|
|
// only run this if feat specific items are requestd
|
|
if (!bDontUseFeats)
|
|
{
|
|
// Weapon Master : Weapon of choise
|
|
// ---------------------------------------------------
|
|
if (GetLevelByClass(CLASS_TYPE_WEAPON_MASTER)>0)
|
|
{
|
|
if (GetHasFeat(959,oAdventurer))
|
|
{
|
|
return 959; // special treatment for dwarven waraxe
|
|
}
|
|
if (GetHasFeat(1000,oAdventurer))
|
|
{
|
|
return 1000; // special treatment for whip
|
|
}
|
|
nRangeStart =943;
|
|
nRangeStop = 919;
|
|
for (i=nRangeStart; i>=nRangeStop;i--)
|
|
{
|
|
if (GetHasFeat(i,oAdventurer))
|
|
return i;
|
|
}
|
|
}
|
|
// ---------------------------------------------------
|
|
|
|
// Checking for Weapon focus and specialications
|
|
|
|
|
|
// Include Weapon Specialication in search range if we have 4+ levels of fighter
|
|
// ---------------------------------------------------
|
|
if (GetLevelByClass(CLASS_TYPE_FIGHTER)>3)
|
|
{
|
|
if (GetHasFeat(953,oAdventurer))
|
|
{
|
|
return 953; // special treatment for dwarven waraxe
|
|
}
|
|
|
|
if (GetHasFeat(994,oAdventurer))
|
|
{
|
|
return 994; // special treatment whip
|
|
}
|
|
|
|
nRangeStart =165; // Weapon Specializations
|
|
nRangeStop = 90; // WeaponFoci Start here
|
|
for (i=nRangeStart; i>=nRangeStop;i--)
|
|
{
|
|
if (GetHasFeat(i,oAdventurer))
|
|
return i;
|
|
}
|
|
}
|
|
// ---------------------------------------------------
|
|
|
|
// Examine Improved Critical
|
|
// ---------------------------------------------------
|
|
if (GetHasFeat(954,oAdventurer))
|
|
{
|
|
return 954; // special treatment for dwarven waraxe
|
|
}
|
|
if (GetHasFeat(995,oAdventurer))
|
|
{
|
|
return 995; // special treatment whip
|
|
}
|
|
|
|
nRangeStart = 89; // Improved
|
|
nRangeStop = 52; // WeaponFoci end here
|
|
for (i=nRangeStart; i>=nRangeStop;i--)
|
|
{
|
|
if (GetHasFeat(i,oAdventurer))
|
|
return i;
|
|
}
|
|
// ---------------------------------------------------
|
|
|
|
|
|
// Examine Weapon Foci
|
|
// ---------------------------------------------------
|
|
if (GetHasFeat(952,oAdventurer))
|
|
{
|
|
return 952; // special treatment for dwarven waraxe
|
|
}
|
|
if (GetHasFeat(993,oAdventurer))
|
|
{
|
|
return 993; // special treatment for whip
|
|
}
|
|
|
|
nRangeStart = 127; // End of weapon foci
|
|
nRangeStop = 90; // WeaponFoci Start here
|
|
for (i=nRangeStart; i>=nRangeStop;i--)
|
|
{
|
|
if (GetHasFeat(i,oAdventurer))
|
|
return i;
|
|
}
|
|
// ---------------------------------------------------
|
|
|
|
}
|
|
|
|
// highest class code
|
|
int nHighest = DTSGetHighestClass(oAdventurer);
|
|
|
|
//Note that the order of the cases in this statement is IMPORTANT!
|
|
switch (nHighest)
|
|
{
|
|
case CLASS_TYPE_WIZARD: //no break is intentional
|
|
case CLASS_TYPE_SORCERER:
|
|
return FEAT_WEAPON_PROFICIENCY_WIZARD;
|
|
break;
|
|
case CLASS_TYPE_ROGUE:
|
|
return FEAT_WEAPON_PROFICIENCY_ROGUE;
|
|
break;
|
|
case CLASS_TYPE_MONK:
|
|
return FEAT_WEAPON_PROFICIENCY_MONK;
|
|
break;
|
|
case CLASS_TYPE_SHIFTER: // no break intentional, we assume shifter == druid
|
|
case CLASS_TYPE_DRUID:
|
|
return FEAT_WEAPON_PROFICIENCY_DRUID;
|
|
break;
|
|
case CLASS_TYPE_PALADIN:
|
|
return 299; // lay on hands
|
|
break;
|
|
case CLASS_TYPE_CLERIC:
|
|
return 294; // turn undead
|
|
break;
|
|
case CLASS_TYPE_SHADOWDANCER:
|
|
return 433; // hide in plain sight
|
|
break;
|
|
case CLASS_TYPE_BARD:
|
|
return 257; // bard songs
|
|
break;
|
|
case CLASS_TYPE_FIGHTER:
|
|
return 657; // some epic weapon spec
|
|
break;
|
|
case CLASS_TYPE_BARBARIAN:
|
|
return 293; // barb rage
|
|
break;
|
|
case CLASS_TYPE_PALEMASTER:
|
|
return 892; // undead graft
|
|
break;
|
|
case CLASS_TYPE_ASSASSIN:
|
|
return 455 ; // death attack
|
|
break;
|
|
case CLASS_TYPE_ARCANE_ARCHER:
|
|
return 445 ; // enchant arrow
|
|
break;
|
|
case CLASS_TYPE_WEAPON_MASTER:
|
|
return 885 ; // ki crit
|
|
break;
|
|
case CLASS_TYPE_BLACKGUARD:
|
|
return 460 ; // bg sneak attack
|
|
break;
|
|
case CLASS_TYPE_DWARVENDEFENDER:
|
|
return 947 ; // defensive stance
|
|
break;
|
|
case CLASS_TYPE_DIVINECHAMPION:
|
|
return 904 ; // sacred defense
|
|
break;
|
|
}
|
|
return 455 ; // class_any
|
|
|
|
}
|
|
|
|
|
|
void DTSGenerateTreasureItems(object oContainer, object oOpener, int nClass, int nType)
|
|
{
|
|
string sItem;
|
|
int nChance = DTSGetBaseChance(GetArea(oContainer));
|
|
|
|
if (nChance == 0)
|
|
return ; // no point in running further code
|
|
|
|
if ((nType & X2_DTS_TYPE_ITEM) && nChance > d100())
|
|
{
|
|
// regardless how often this function is called, only one char
|
|
// specific treasure item will be created ... ever
|
|
if (!GetLocalInt(oContainer, "X2_DTS_HAS_CHAR_SPECIFIC_TREASURE"))
|
|
{
|
|
DTSGenerateCharSpecificTreasure(oContainer, oOpener);
|
|
SetLocalInt(oContainer, "X2_DTS_HAS_CHAR_SPECIFIC_TREASURE", TRUE);
|
|
}
|
|
}
|
|
if ((nType & X2_DTS_TYPE_GOLD) && nChance > d100())
|
|
{
|
|
if (!GetLocalInt(oContainer, "X2_DTS_HAS_GOLD"))
|
|
{
|
|
sItem = DTSGetRandomItemResRef(X2_DTS_TYPE_GOLD, nClass);
|
|
DTSCreateItemOnObject(sItem, oContainer);
|
|
SetLocalInt(oContainer, "X2_DTS_HAS_GOLD", TRUE);
|
|
}
|
|
}
|
|
if ((nType & X2_DTS_TYPE_DISP) && nChance > d100())
|
|
{
|
|
sItem = DTSGetRandomItemResRef(X2_DTS_TYPE_DISP, nClass);
|
|
DTSCreateItemOnObject(sItem, oContainer);
|
|
}
|
|
if ((nType & X2_DTS_TYPE_AMMO) && nChance > d100())
|
|
{
|
|
sItem = DTSGetRandomItemResRef(X2_DTS_TYPE_AMMO, nClass);
|
|
DTSCreateItemOnObject(sItem, oContainer);
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
int DTSGetNumberofPartyMembers(object oPC)
|
|
{
|
|
object oCount = GetFirstFactionMember(oPC,TRUE);
|
|
int nCount;
|
|
while (oCount !=OBJECT_INVALID)
|
|
{
|
|
nCount++;
|
|
oCount = GetNextFactionMember(oPC,TRUE);
|
|
}
|
|
return nCount ;
|
|
}
|
|
|
|
|
|
|
|
// +++ PUBLIC FUNCTIONS +++
|
|
|
|
|
|
|
|
//::///////////////////////////////////////////////
|
|
//:: DTSGenerateTreasureOnContainer
|
|
//:: Copyright (c) 2003 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Generate random, disposeable treasure on the container
|
|
oContainer - Valid object with inventory
|
|
nClass - Treasure Class (X2_DTS_CLASS_*)
|
|
nType - Treasure Type (X2_DTS_TYPE_*), default = X2_DTS_TYPE_DISPOSEABLE (1) | X2_DTS_TYPE_GOLD (4)
|
|
Example
|
|
Generate Low Class Ammo and Gold+Gems
|
|
DTSGenerateTreasureOnContainer (oChest, X2_DTS_CLASS_LOW, X2_DTS_TYPE_AMMO | X2_DTS_TYPE_GOLD);
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By: Georg Zoeller
|
|
//:: Created On: 2003-06-03
|
|
//:://////////////////////////////////////////////
|
|
void DTSGenerateTreasureOnContainer (object oContainer, object oOpener, int nClass, int nType = 5)
|
|
{
|
|
int nCount;
|
|
int nMax = Random(DTSGetMaxItems())+1;
|
|
|
|
// Add one more item per two partymembers
|
|
// nMax += (DTSGetNumberofPartyMembers(oOpener) /2) ;
|
|
|
|
for (nCount = 0; nCount <= nMax; nCount++)
|
|
{
|
|
DTSGenerateTreasureItems(oContainer, oOpener, nClass, nType);
|
|
}
|
|
|
|
// Remove flags set within DTSGenerateTreasureItems
|
|
DeleteLocalInt(oContainer, "X2_DTS_HAS_CHAR_SPECIFIC_TREASURE");
|
|
DeleteLocalInt(oContainer, "X2_DTS_HAS_GOLD");
|
|
}
|
|
|
|
|
|
//::///////////////////////////////////////////////
|
|
//:: DTSGenerateCharSpecificTreasure
|
|
//:: Copyright (c) 2003 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Generate random, disposeable treasure on the container
|
|
oContainer - Valid object with inventory
|
|
nClass - Treasure Class (X2_DTS_CLASS_*)
|
|
nType - Treasure Type (X2_DTS_TYPE_*), default = X2_DTS_TYPE_DISPOSEABLE (1) | X2_DTS_TYPE_GOLD (4)
|
|
bIgnoreFeat - do not examine weapon feats when creating items, instead use class only
|
|
Example
|
|
Generate Low Class Ammo and Gold+Gems
|
|
DTSGenerateTreasureOnContainer (oChest, X2_DTS_CLASS_LOW, X2_DTS_TYPE_AMMO | X2_DTS_TYPE_GOLD);
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By: Georg Zoeller
|
|
//:: Created On: 2003-06-04
|
|
//:://////////////////////////////////////////////
|
|
object DTSGenerateCharSpecificTreasure (object oContainer, object oAdventurer, int bIgnoreFeats = FALSE)
|
|
{
|
|
|
|
int nFeat = DTSDetermineFeatToUse(oAdventurer,bIgnoreFeats);
|
|
string sItem ;
|
|
object oRet;
|
|
if (nFeat == -1) // did not find a feat, try class specific code
|
|
{
|
|
DTSDebug("Did not find a feat for specific treasure for "+ GetName(oAdventurer));
|
|
}
|
|
else
|
|
{
|
|
sItem = DTSGetFeatSpecificItemResRef(nFeat);
|
|
oRet = DTSCreateItemOnObject(sItem, oContainer);
|
|
}
|
|
|
|
return oRet;
|
|
}
|
|
|
|
|
|
|
|
void DTSInitialize( int nConfigIndex = 0)
|
|
{
|
|
int nBaseChance = StringToInt(DTSGet2DAStringOrDefault(X2_DTS_2DA_CONF, "BaseTreasureChance", nConfigIndex, IntToString(X2_DTS_BASECHANCE_TREAS)));
|
|
int nMaxItems = StringToInt(DTSGet2DAStringOrDefault(X2_DTS_2DA_CONF, "MaxItems", nConfigIndex, IntToString(X2_DTS_MAXITEMS)));
|
|
// using int because Get2DAString does not work well with floats
|
|
int nStackVariation = StringToInt(DTSGet2DAStringOrDefault(X2_DTS_2DA_CONF, "StackVariation", nConfigIndex, IntToString(X2_DTS_STACKVAR)));
|
|
float fStackVariation = nStackVariation / 100.0f;
|
|
if (fStackVariation == 0.0f)
|
|
{
|
|
fStackVariation = X2_DTS_STACKVAR / 100.0f ;
|
|
}
|
|
|
|
string s2DA = DTSGet2DAStringOrDefault(X2_DTS_2DA_CONF, "Gold2da", nConfigIndex,X2_DTS_2DA_GOLD );
|
|
SetLocalString(GetModule(),"X2_DTS_2DA_GOLD", s2DA);
|
|
s2DA = DTSGet2DAStringOrDefault(X2_DTS_2DA_CONF, "Item2DA",nConfigIndex,X2_DTS_2DA_ITEM );
|
|
SetLocalString(GetModule(),"X2_DTS_2DA_ITEM", s2DA);
|
|
s2DA = DTSGet2DAStringOrDefault(X2_DTS_2DA_CONF, "Ammo2DA", nConfigIndex,X2_DTS_2DA_AMMO );
|
|
SetLocalString(GetModule(),"X2_DTS_2DA_AMMO", s2DA);
|
|
s2DA = DTSGet2DAStringOrDefault(X2_DTS_2DA_CONF, "Disp2DA", nConfigIndex,X2_DTS_2DA_DISP );
|
|
SetLocalString(GetModule(),"X2_DTS_2DA_DISP", s2DA);
|
|
|
|
SetLocalInt(GetModule(),"X2_DTS_BASECHANCE",nBaseChance);
|
|
SetLocalFloat(GetModule(),"X2_DTS_STACKVAR",fStackVariation);
|
|
SetLocalInt(GetModule(),"X2_DTS_MAXITEMS",nMaxItems);
|
|
|
|
//DTSDebug("DTS Initialized - BaseChance: " + IntToString(nBaseChance) + " StackVar: " + FloatToString(fStackVariation) + " MaxItems: " + IntToString(nMaxItems));
|
|
}
|
|
|
|
// Sets the area wide chance for treasure Generation ...
|
|
// if bDisable = TRUE, then no random treasure is generated at all
|
|
void DTSSetAreaTreasureProbability(object oArea, int nBaseChance, int bDisabled = FALSE)
|
|
{
|
|
if (bDisabled)
|
|
SetLocalInt(oArea,"X2_DTS_BASECHANCE",-1); // -1 = no treasure
|
|
else
|
|
SetLocalInt(oArea,"X2_DTS_BASECHANCE",nBaseChance);
|
|
|
|
}
|
|
|
|
//:: Test void
|
|
//:: void main (){}
|