Shargast_PRC8/_module/Chapter 2/nss/x0_i0_treasure.nss
Jaysyn904 66a0a3e043 Initial commit
Initial commit.
2024-08-03 14:13:18 -04:00

1435 lines
53 KiB
Plaintext

//:://////////////////////////////////////////////////
//:: X0_I0_TREASURE
//:: Modified by Shayan on Jan/05/2005
//Include library for XP1 treasure generation system.
//--------------------------------------------------
//MODIFICATIONS
//:: Modifications: When asked to generate treasure for a creature, the script
//:: now takes into account the creature's Challenge rating and then rolls for
//:: either an item from unique or high or medium or low or even the junk chest. The percentage
//:: chance of getting items from each of these chests can be varied by adjusting
//:: the constant ints below.
//:: SETTING UP THIS SCRIPT
//
// Step 1: Import in and override (If you can read this then you've done it *Duh!*).
//
//
// Step 2: Create an area -inaccessible to players- with 5 chests.
// Change the tags of the chests to: X0_MOD_TREASURE_JUNK, X0_MOD_TREASURE_LOW, X0_MOD_TREASURE_MEDIUM
// X0_MOD_TREASURE_HIGH, and X0_MOD_TREASURE_UNIQUE.
//
// Step 3: Give all the chests an inventory, and fill them up with items that you want generated in random treasure
// generation. Make sure that you put appropriate items in appropriate chests. IE: Put items of little value in
// the junk chest, and items of great significance in the Unique chest.
//
// Step 4: Test out the treasure system. If you don't like the percentage of generation you can always change the values below.
//
//
//::
//:: Steps in treasure generation for a monster (with this script):
//::
//:: Step 1:
//:: Rolls a dice with 100 faces to see if a value of greater than BK_CHANCE_OF_N0_MONSTERTREASURE (refer to below)
//:: comes up. If not then it stops and no random treasure is generated.
//::
//:: Step 2:
//:: Checks for any area specific chest, if there is one then treasure is generated from there (Note: This is generated
//:: using BioWare's random treasure script). If there is no area specific chest, then it will look in the module for a
//:: Module wide monster chest (Note: This is generated using BioWare's random treasure script).
//::
//:: Step 3:
//:: Now if there aren't any monster specific or base area chest, then the treasure system looks for any general Module wide chests.
//:: HERE is where this script modification comes into work.
//:: - Assuming you have setup the system appropriately, there are 5 chests: Junk, Low, Medium, High and Unique.
//:: - Now the script takes into account the creature's challenge rating and rolls against the values as explained by
//:: Probablity of generation (see below).
//:: - In a nutshell, Creatures with high Challenge Rating (or CR) will have a better chance of spawning Unique item(s).
//:: Creatures with low CR will most likely spawn items from the junk,low or medium chest (it all depends on the dice rolls)
//:: - Essentially the higher the CR the better the items.
//::
//:: NOTE: Items in the "Unique" chest will/may spawn again. Unique does not mean once only. There is no database use in this script
// hence nothing is ever persistent. Unique chest is simply a chest that should ideally contain items of higher 'value' than
// the junk, low, medium, or high chests.
//:: Formula used for generation is explained in the appropriate method.
//:: Never fear... all other functions of the treasure script works as per normal
//:: IE: Generating a specific treasure from a chest, etc.
//
//:: Probability of Generation for Item from chest (Unique, High, Medium, or Low)
// XXXXX_SPAWN_MAX_PERCENTAGE
// = --------------------------------------------- X (Creature's challenge rating)^2
// (XXXXX_SPAWN_MAX_PERCENTAGE_AT_CREATURE_CR)^2)
//::NOTE: XXXX_SPAWN_MAX_PERCENTAGE and XXXX_SPAWN_MAX_PERCENTAGE_AT_CREATURE_CR refers to the constants below.
const int BK_CHANCE_OF_N0_MONSTERTREASURE = 65;
const float LOW_SPAWN_MAX_PERCENTAGE = 100.0;
const float LOW_SPAWN_MAX_PERCENTAGE_AT_CREATURE_CR = 60.0;
const float MEDIUM_SPAWN_MAX_PERCENTAGE = 100.0;
const float MEDIUM_SPAWN_MAX_PERCENTAGE_AT_CREATURE_CR = 80.0;
const float HIGH_SPAWN_MAX_PERCENTAGE = 100.0;
const float HIGH_SPAWN_MAX_PERCENTAGE_AT_CREATURE_CR = 100.0;
const float UNIQUE_SPAWN_MAX_PERCENTAGE = 100.0;
const float UNIQUE_SPAWN_MAX_PERCENTAGE_AT_CREATURE_CR = 200.0;
//NOTE: There is no adjustable value for the Junk chest. If all else fails, an item from the junk chest will be generated atleast.
// Example: Take a creature with CR 20. Given that it passes the Step 1 of the treasure generation phase,
// and there are no area specfic and base area chests, then:
// 100
// The chances of it spawning with item(s) from the 'Low' chest is: ------- X 20^2 = 11.1%
// 60^2
//
// 100
// The chances of it spawning with item(s) from the 'Medium' chest is: ------- X 20^2 = 6.25%
// 80^2
//
// 100
// The chances of it spawning with item(s) from the 'High' chest is: ------- X 20^2 = 4%
// 100^2
//
// 100
// The chances of it spawning with item(s) from the 'Unique' chest is: ------- X 20^2 = 0.05%
// 100^2
//So in this case the creature is most likely to spawn with an item from the Junk chest as the chances of it getting any item from the other
//chests are very low.
// Example 2: Take a creature with CR 40. Given that it passes the Step 1 of the treasure generation phase,
// and there are no area specfic and base area chests, then:
// 100
// The chances of it spawning with item(s) from the 'Low' chest is: ------- X 40^2 = 44.4%
// 60^2
//
// 100
// The chances of it spawning with item(s) from the 'Medium' chest is: ------- X 40^2 = 25%
// 80^2
//
// 100
// The chances of it spawning with item(s) from the 'High' chest is: ------- X 40^2 = 16%
// 100^2
//
// 100
// The chances of it spawning with item(s) from the 'Unique' chest is: ------- X 40^2 = 4%
// 100^2
//So in this case the creature is most likely to spawn with an item from the Low, or Medium chests as the chances of it getting any item from the other
//chests are less.
//Note: Depending on the the amount of treasure you want distributed adjust the above values. If you are running a low treasure module
// then lower the percentage the better. If you are running a module with valuable loot given by all monsters then, of course higher the
// percentage the better.
// Tags for the module-wide containers
string sModContJunk = "X0_MOD_TREASURE_JUNK";
string sModContLow = "X0_MOD_TREASURE_LOW";
string sModContMed = "X0_MOD_TREASURE_MEDIUM";
string sModContHigh = "X0_MOD_TREASURE_HIGH";
string sModContUniq = "X0_MOD_TREASURE_UNIQUE";
//:: Throw dices to determine whether the PC is eligable for an Item Spawn
//:: creatureCR is the spawned creature's (IE: OBJECT_SELF) challenge rating.
//:: pMax is the Maximum percentage chance of item generation at cMax.
//:: cMax is the Highest creature's challenge rating.
//:: IE: If the pMax == 100, and cMax == 40, then the chance of an item
//:: spawn on a creature with challenge rating of 40 is 100%.
//::
//:: For all values above @threshold, returns TRUE. IE: Will spawn item.
//:: The chance of item generation is determined using a quardratic formula:
//:: Probability of Generation = (pMax/(cMax)^2)*(creatureCR)^2
//::
//:: Using the above example, this means that the chance of a unique item spawn
//:: on a creature with CR 20 is: 25%
//::
//:: WARNING: cMax squared must be greater than pMax AND creatureCR must be less than cMax
//:: for this to function properly... other wise it will always return true. (Calculate the
//:: probability for yourself and see ;)!!
int RollForItemSpawn(float creatureCR, float pMax = 100.0, float cMax = 40.0);
//return the chest appropriate to reward the PC
string GetAppropriateChest(float fRating);
/*
MAIN CONCEPT:
The module builder creates some base containers and fills them
with instances of the treasure items that s/he wants to appear
randomly. The actual treasure containers then randomly pick from
the contents of these base containers to generate their own
contents.
--------------------------------------------------
SETUP:
Create four module-wide base containers (for low, medium, high,
and unique treasure items) and place them anywhere in your
module. Make sure that they are in locations inaccessible to the
players, though!
Give these module-wide base containers these tags (or just use the
blueprints):
X0_MOD_TREASURE_LOW - low-level treasure
X0_MOD_TREASURE_MED - medium-level treasure
X0_MOD_TREASURE_HIGH - high-level treasure
X0_MOD_TREASURE_UNIQ - unique treasure items
Fill the instances of these base containers with appropriate treasure
for your module.
For any areas where you want finer control over the treasure,
simply create additional base containers (you don't need all four
-- any one that you skip will fall back to the module-wide version)
and place them in the area. Give them these tags (same just without
the "MOD"):
X0_TREASURE_LOW - low-level treasure
X0_TREASURE_MED - medium-level treasure
X0_TREASURE_HIGH - high-level treasure
X0_TREASURE_UNIQ - unique treasure items
For any treasure container, use one of the following scripts
as BOTH the OnOpen/OnDeath handler:
Any Treasure: x0_o2_any{low,med,high,uniq}
Books (book, scroll): x0_o2_book{low,med,high,uniq}
Potions: x0_o2_potn{low,med,high,uniq}
Armor (armor, shield, helm, boots, etc): x0_o2_arm{low,med,high,uniq}
Weapon: x0_o2_weap{low,med,high,uniq}
Gold: x0_o2_gold{low,med,high,uniq}
Others may also be added.
MONSTER/NPC TREASURE
--------------------
If you would like to have special monster treasure (monster treasure
defaults to low treasure otherwise), you can also add any of these
base chests:
X0_TREASURE_MONSTER_<monster tag> - treasure found on monsters with
the given tag. This will strip off
any trailing digits, so for instance,
NW_KOBOLD1, NW_KOBOLD2, NW_KOBOLD005
would all end up checking the chest
X0_TREASURE_MONSTER_NW_KOBOLD.
X0_TREASURE_MONSTER_<racialtype> - treasure found on monsters of the given
racialtype. Ex:
X0_TREASURE_MONSTER_ELF
X0_TREASURE_MONSTER_UNDEAD
The spelling matches that used in the
RACIALTYPE_* constants.
X0_TREASURE_MONSTER - generic treasure found on all monsters/NPCs
in the module.
To use monster treasure, use the default OnSpawn script nw_c2_default9
or modify the OnSpawn script as follows:
- Replace #include "nw_o2_coninclude" with #include "x0_i0_treasure"
- Replace GenerateNPCTreasure(); with CTG_GenerateNPCTreasure();
- If you prefer to generate monster treasure from the general chests,
you can also add a parameter to CTG_GenerateNPCTreasure(); to
specify whether the treasure generated should be low/medium/high/uniq.
See the comments to that function for details.
--------------------------------------------------
DETAILS:
Each treasure container has a script that looks for the
nearest object with the tag matching the type of
treasure.
When the treasure-generating scripts look for a container,
they will take the nearest container in the local, then
fall back to the module-wide container. If no container can
be found, they will fall back on the standard random treasure
generation system.
The treasure generation system will randomly select from
1-3 items from whatever items are in the nearest container.
Each item has a 50/50 chance of being replaced by a random
amount of coin based on the standard treasure generation
system.
IMPORTANT NOTE ON PROBABILITY:
Each item in the chest has an equal probability of being
selected. To control the probability of any given item
appearing, simply place multiple copies of it in the container.
Because of the stacking rules, there is a slight modification
to this. Ammunition/throwing weapons will have a probability
equal to the number of stacks in the chest, since the max stack
size is the default stack size. Potions, scrolls, and gems, however,
will be counted individually to determine the probability even if
they are stacked, since their default stack size is 1.
To control the size of the stack that actually gets created, you
should create a blueprint that has the appropriate stack size.
You can adjust the stack size of the instance you stuff into the
base container to whatever you want afterwards; the blueprint's
stack size will control what
There are scripts that will cause only specific types of items
to be selected from the container of the specified level --
eg, only books/scrolls, or only weapons or armor, etc -- useful
for bookcases or for weapon racks, & so on.
The unique treasure chest will only place each item in the
chest once, will never place more than one item, and will
never replace the item with coin.
Advantages of this system:
- Complete control over which items can appear in a
module or in an area.
- Thematically-appropriate treasure can be placed in each
area.
- Easy for module builders to set up.
- Trivial to add new items to the treasure distribution.
- Trivial to adjust probabilities of items appearing.
- Easy to have unique treasure items showing up randomly.
Disadvantages of this system:
- No level-specific treasure generation. This system is thus
NOT appropriate for an area that is intended to scale to
radically-different levels. Rather, it is appropriate for
use where the levels of the characters are roughly known
to the module designer and the treasure can be designed to
match.
- No class-specific treasure generation planned for now.
(However, I may add something to increase probability of
certain items popping up, optionally. TBD.)
For XP1, we feel this is a good tradeoff, but this should
be kept in mind when deciding whether to use this system or
the original treasure generation system in user-made modules.
-- NN
*/
//:://////////////////////////////////////////////////
//:: Copyright (c) 2002 Floodgate Entertainment
//:: Created By: Naomi Novik
//:: Created On: 11/16/2002
//:://////////////////////////////////////////////////
// For legacy treasure generation
#include "nw_o2_coninclude"
/**********************************************************************
* CONSTANTS
**********************************************************************/
// * this is the percent chance that no treasure will be spawned by a creature dying
// Tags for the area-specific containers
string sContJunk = "X0_TREASURE_JUNK";
string sContLow = "X0_TREASURE_LOW";
string sContMed = "X0_TREASURE_MED";
string sContHigh = "X0_TREASURE_HIGH";
string sContUniq = "X0_TREASURE_UNIQ";
// Tag for the monster-specific containers
string sContMonster = "X0_TREASURE_MONSTER";
// Gold item ResRef
string sGoldResRef = "NW_IT_GOLD001";
// Varname holding the number of treasure items
string sNumTreasureItemsVarname = "X0_NUM_TREASURE_ITEMS";
// Varname holding the base type of each treasure item
string sBaseTypeVarname = "X0_BASE_TYPE_TREASURE";
// Varname holding a reference to each treasure item
string sTreasureItemVarname = "X0_TREASURE_ITEM";
// Varname indicating that the treasure container has been filled
string sTreasureGeneratedVarname = "X0_TREASURE_HAS_BEEN_GENERATED";
// Major treasure categories
int TREASURE_TYPE_LOW = 1;
int TREASURE_TYPE_MED = 2;
int TREASURE_TYPE_HIGH = 3;
int TREASURE_TYPE_UNIQUE = 4;
int TREASURE_TYPE_MONSTER = 5;
int TREASURE_TYPE_JUNK = 6;
// Special generalized base types.
// Giving these large values to make sure they never
// conflict with the actual base type values -- that
// would cause those base types to be non-specifiable.
int TREASURE_BASE_TYPE_WEAPON = 13000;
int TREASURE_BASE_TYPE_WEAPON_NOAMMO = 13001;
int TREASURE_BASE_TYPE_WEAPON_RANGED = 13002;
int TREASURE_BASE_TYPE_WEAPON_MELEE = 13003;
int TREASURE_BASE_TYPE_ARMOR = 13004;
int TREASURE_BASE_TYPE_CLOTHING = 13005;
// Probability of a single item being generated,
// in percentage
int TREASURE_PROBABILITY_1 = 70;
// Probability of two items being generated,
// in percentage
int TREASURE_PROBABILITY_2 = 20;
// Probability of an item being converted to gold
int TREASURE_GOLD_PROBABILITY = 35;
// Multiplier to use on the value of an item to convert it to gold
float X0_GOLD_MODIFIER = 0.50;
/**********************************************************************
* FUNCTION PROTOTYPES
*
* All functions prefixed with CTG for "container treasure generation".
**********************************************************************/
// Get the number of items to generate
// Returns an integer from 1-3, probabilities
// determined by the values of the constants
// TREASURE_PROBABILITY_1 & _2.
int CTG_GetNumItems();
// Get the number of items in a base container.
int CTG_GetNumItemsInBaseContainer(object oBaseCont);
// Determine whether an item should actually just be gold.
// Returns TRUE or FALSE.
// Probability controlled by constant TREASURE_GOLD_PROBABILITY
int CTG_IsItemGold();
// Find and return the right monster container, if
// available.
object CTG_GetMonsterBaseContainer(object oSource=OBJECT_SELF);
// Locate the base container of the appropriate type closest to
// oSource.
// Possible values for nTreasureType:
// TREASURE_TYPE_LOW
// TREASURE_TYPE_MED
// TREASURE_TYPE_HIGH
// TREASURE_TYPE_UNIQUE
object CTG_GetNearestBaseContainer(int nTreasureType, object oSource=OBJECT_SELF);
// Get the module-wide base container of the appropriate type.
// Possible values for nTreasureType:
// TREASURE_TYPE_LOW
// TREASURE_TYPE_MED
// TREASURE_TYPE_HIGH
// TREASURE_TYPE_UNIQUE
object CTG_GetModuleBaseContainer(int nTreasureType);
// Get the specified item out of the given base container's inventory
object CTG_GetTreasureItem(object oBaseCont, int nItemNum);
// Test if treasure has been generated in the given object
int CTG_GetIsTreasureGenerated(object oCont);
// Set whether treasure has been generated
void CTG_SetIsTreasureGenerated(object oCont, int bGenerated=TRUE);
// Create random treasure items of the appropriate type
// in the specified container. Will typically be called
// by a script on a treasure container.
//
// Possible values for nTreasureType:
// TREASURE_TYPE_LOW
// TREASURE_TYPE_MED
// TREASURE_TYPE_HIGH
// TREASURE_TYPE_UNIQUE
void CTG_CreateTreasure(int nTreasureType, object oAdventurer, object oCont=OBJECT_SELF);
// Starting from the specified item position, return the first
// item that matches one of the three base types.
//
// nBaseType1 may also be passed in as a special custom type,
// which will OVERRIDE any other specified base types:
//
// TREASURE_BASE_TYPE_WEAPON (for any weapon type)
// TREASURE_BASE_TYPE_WEAPON_NOAMMO (for any weapon but ammunition)
// TREASURE_BASE_TYPE_WEAPON_RANGED (for any ranged weapon)
// TREASURE_BASE_TYPE_WEAPON_MELEE (for any melee weapon)
// TREASURE_BASE_TYPE_ARMOR (for armor, shields)
// TREASURE_BASE_TYPE_CLOTHING (for belts, boots, bracers,
// cloaks, helms, gloves)
object CTG_GetSpecificBaseTypeTreasureItem(object oBaseCont, int nItemNum, int nBaseType1=BASE_ITEM_INVALID, int nBaseType2=BASE_ITEM_INVALID, int nBaseType3=BASE_ITEM_INVALID);
// Create treasure of the appropriate treasure level and matching one
// of up to three different base types in the specified container.
//
// Possible values for nTreasureType:
// TREASURE_TYPE_LOW
// TREASURE_TYPE_MED
// TREASURE_TYPE_HIGH
// TREASURE_TYPE_UNIQUE
//
// Possible values for nBaseType1/2/3: any BASE_ITEM_* constant.
//
// If nBaseType1 is passed in as invalid, NO TYPE CHECKING WILL BE DONE.
//
// nBaseType1 may also be passed in as a special custom type,
// which will OVERRIDE any other specified base types:
//
// TREASURE_BASE_TYPE_WEAPON (for any weapon type)
// TREASURE_BASE_TYPE_WEAPON_NOAMMO (for any weapon but ammunition)
// TREASURE_BASE_TYPE_WEAPON_RANGED (for any ranged weapon)
// TREASURE_BASE_TYPE_WEAPON_MELEE (for any melee weapon)
// TREASURE_BASE_TYPE_ARMOR (for armor, shields)
// TREASURE_BASE_TYPE_CLOTHING (for belts, boots, bracers,
// cloaks, helms, gloves)
//
void CTG_CreateSpecificBaseTypeTreasure(int nTreasureType, object oAdventurer, object oCont, int nBaseType1=BASE_ITEM_INVALID, int nBaseType2=BASE_ITEM_INVALID, int nBaseType3=BASE_ITEM_INVALID);
// Create gold treasure in the specified container.
void CTG_CreateGoldTreasure(int nTreasureType, object oAdventurer, object oCont=OBJECT_SELF);
// Create treasure on an NPC.
// This function will typically be called from within the
// NPC's OnSpawn handler.
// Note that this defaults to TREASURE_TYPE_MONSTER, which uses
// the monster-specific treasure chests and falls back to low-
// level treasure if none exist.
void CTG_GenerateNPCTreasure(int nTreasureType=5, object oNPC=OBJECT_SELF);
// Check if the item's base type is of the given base type
int CTG_GetIsBaseType(int nItemBaseType, int nBaseType1=BASE_ITEM_INVALID, int nBaseType2=BASE_ITEM_INVALID, int nBaseType3=BASE_ITEM_INVALID);
// Check if the item's base type is a weapon
int CTG_GetIsWeapon(int nItemBaseType);
// Check if the item's base type is a weapon but not ammunition
int CTG_GetIsWeaponNoammo(int nItemBaseType);
// Check if the item's base type is a ranged weapon
int CTG_GetIsRangedWeapon(int nItemBaseType);
// Check if the item's base type is a melee weapon
int CTG_GetIsMeleeWeapon(int nItemBaseType);
// Check if the item's base type is armor
int CTG_GetIsArmor(int nItemBaseType);
// Check if the item's base type is clothing
int CTG_GetIsClothing(int nItemBaseType);
// Tack on the appropriate racialtype suffix
string CTG_GetRacialtypeChestTag(string sBaseTag, object oSource);
/**********************************************************************
* PRIVATE FUNCTION DEFINITIONS
* These functions are deliberately not prototyped and not intended
* for use outside this library.
**********************************************************************/
//:: Throw dices to determine whether the PC is eligable for an Item Spawn
//:: creatureCR is the spawned creature's (IE: OBJECT_SELF) challenge rating.
//:: pMax is the Maximum percentage chance of item generation at cMax.
//:: cMax is the Highest creature's challenge rating.
//:: IE: If the pMax == 100, and cMax == 40, then the chance of an item
//:: spawn on a creature with challenge rating of 40 is 100%.
//::
//:: For all values above @threshold, returns TRUE. IE: Will spawn item.
//:: The chance of item generation is determined using a quardratic formula:
//:: Probability of Generation = (pMax/(cMax)^2)*(creatureCR)^2
//::
//:: Using the above example, this means that the chance of a unique item spawn
//:: on a creature with CR 20 is: 25%
//::
//:: WARNING: cMax squared must be greater than pMax AND creatureCR must be less than cMax
//:: for this to function properly... other wise it will always return true. (Calculate the
//:: probability for yourself and see ;)!!
int RollForItemSpawn(float creatureCR, float pMax = 40.0, float cMax = 100.0)
{
cMax = cMax*cMax;
creatureCR = creatureCR*creatureCR;
float oMax = pMax/cMax;
float detPercentage = oMax*creatureCR;
//to make detPercentage a whole number
detPercentage = detPercentage*1000.0;
if(detPercentage < 0.5)
{
detPercentage = 0.0;
}
int detChance = FloatToInt(detPercentage);
//returns TRUE if the dice roll
int nDiceRoll = Random(100000) + 1;
return (nDiceRoll <= detChance);
}
string GetAppropriateChest(float fRating)
{
int UniqueRoll = RollForItemSpawn(fRating, UNIQUE_SPAWN_MAX_PERCENTAGE, UNIQUE_SPAWN_MAX_PERCENTAGE_AT_CREATURE_CR);
int HighRoll = RollForItemSpawn(fRating, HIGH_SPAWN_MAX_PERCENTAGE, HIGH_SPAWN_MAX_PERCENTAGE_AT_CREATURE_CR);
int MediumRoll = RollForItemSpawn(fRating, MEDIUM_SPAWN_MAX_PERCENTAGE, MEDIUM_SPAWN_MAX_PERCENTAGE_AT_CREATURE_CR);
int LowRoll = RollForItemSpawn(fRating,LOW_SPAWN_MAX_PERCENTAGE, LOW_SPAWN_MAX_PERCENTAGE_AT_CREATURE_CR);
if(UniqueRoll)
{
return sModContUniq;
}
else if (HighRoll)
{
return sModContHigh;
}
else if (MediumRoll)
{
return sModContMed;
}
else if (LowRoll)
{
return sModContLow;
}
else
{ //or junk
return sModContJunk;
}
}
// This function deliberately not prototyped. Should not be used
// outside this library.
// Test whether a treasure container has been initialized for
// specific base treasure type use.
int CTG_GetIsContainerInitialized(object oBaseCont)
{
return GetLocalInt(oBaseCont, "X0_CONTAINER_INITIALIZED");
}
// This function deliberately not prototyped. Should not be used
// outside this library.
// Set whether a treasure container has been initialized for
// specific base treasure type use.
void CTG_SetIsContainerInitialized(object oBaseCont, int bInit=TRUE)
{
SetLocalInt(oBaseCont, "X0_CONTAINER_INITIALIZED", bInit);
}
// This function deliberately not prototyped. Should not be used
// outside this library.
// Initialize a treasure container to store the items contained
// inside as local variables on the container.
void CTG_InitContainer(object oBaseCont)
{
// don't do this twice
if (CTG_GetIsContainerInitialized(oBaseCont)) {return;}
// initialize
int nItems = CTG_GetNumItemsInBaseContainer(oBaseCont);
int i;
object oTmp = OBJECT_INVALID;
oTmp = GetFirstItemInInventory(oBaseCont);
for (i=0; i < nItems && GetIsObjectValid(oTmp); i++)
{
// Store the item and its base type as local vars on
// the container object itself.
string sIndex = IntToString(i);
string sVar = sBaseTypeVarname + sIndex;
SetLocalInt(oBaseCont, sVar, GetBaseItemType(oTmp));
sVar = sTreasureItemVarname + sIndex;
SetLocalObject(oBaseCont, sVar, oTmp);
oTmp = GetNextItemInInventory(oBaseCont);
}
// mark as initialized
CTG_SetIsContainerInitialized(oBaseCont);
}
/**********************************************************************
* FUNCTION DEFINITIONS
**********************************************************************/
// Get the number of items to generate
// Returns an integer from 1-3, probabilities
// determined by the values of the constants
// TREASURE_PROBABILITY_1 & _2.
int CTG_GetNumItems()
{
int nRoll = d100();
if (nRoll < TREASURE_PROBABILITY_1) {
return 1;
} else if (nRoll < (TREASURE_PROBABILITY_1 + TREASURE_PROBABILITY_2)) {
return 2;
}
return 3;
}
// Get the number of items in a base container
int CTG_GetNumItemsInBaseContainer(object oBaseCont)
{
int nItems = GetLocalInt(oBaseCont, sNumTreasureItemsVarname);
if (nItems != 0) {
return nItems;
}
// Haven't initialized the number of items yet
object oTmp = GetFirstItemInInventory(oBaseCont);
while (GetIsObjectValid(oTmp)) {
nItems++;
oTmp = GetNextItemInInventory(oBaseCont);
}
SetLocalInt(oBaseCont, sNumTreasureItemsVarname, nItems);
return nItems;
}
// Determine whether an item should actually just be gold.
// Returns TRUE or FALSE.
// Probability controlled by constant TREASURE_GOLD_PROBABILITY
int CTG_IsItemGold()
{
int nRoll = d100();
if (nRoll < TREASURE_GOLD_PROBABILITY)
return TRUE;
return FALSE;
}
int GetIsInteger(string sChar)
{
return (sChar == "0"
|| sChar == "1"
|| sChar == "2"
|| sChar == "3"
|| sChar == "4"
|| sChar == "5"
|| sChar == "6"
|| sChar == "7"
|| sChar == "8"
|| sChar == "9");
}
// Find and return the right monster container, if
// available.
object CTG_GetMonsterBaseContainer(object oSource=OBJECT_SELF)
{
object oCont = OBJECT_INVALID;
string sContTag = "";
// For monster treasure, we first check for
// a chest with a tag matching the specific
// monster.
// We strip numbers off the end of the tag first
string sCreatureTag = GetTag(oSource);
while ( GetIsInteger(GetStringRight(sCreatureTag, 1)) ) {
sCreatureTag = GetStringLeft(sCreatureTag,
GetStringLength(sCreatureTag)-1);
}
sContTag = sContMonster + "_" + sCreatureTag;
oCont = GetObjectByTag(sContTag);
if (GetIsObjectValid(oCont)) {
return oCont;
}
// Didn't find that -- check for a chest for the
// appropriate racialtype.
sContTag = CTG_GetRacialtypeChestTag(sContMonster, oSource);
oCont = GetObjectByTag(sContTag);
if (GetIsObjectValid(oCont)) {
return oCont;
}
// Didn't find that -- check for a module-wide
// monster chest
oCont = GetObjectByTag(sContMonster);
return oCont;
}
// Locate the nearest base container of the appropriate type.
// Possible values for nTreasureType:
// TREASURE_TYPE_MONSTER
// TREASURE_TYPE_LOW
// TREASURE_TYPE_MED
// TREASURE_TYPE_HIGH
// TREASURE_TYPE_UNIQUE
object CTG_GetNearestBaseContainer(int nTreasureType,
object oSource=OBJECT_SELF)
{
object oCont = OBJECT_INVALID;
int nType = nTreasureType;
string sContTag = "";
if (nType == TREASURE_TYPE_MONSTER)
{
oCont = CTG_GetMonsterBaseContainer(oSource);
if (GetIsObjectValid(oCont))
{
return oCont;
}
//if there are no areas specific chests then roll module wide chest based
//on challenge rating.
else
{
float creatureCR = GetChallengeRating(oSource);
string ChestChosen = GetAppropriateChest(creatureCR);
oCont = GetObjectByTag(ChestChosen);
if(GetIsObjectValid(oCont))
{
return oCont;
}
}
// no monster-specific treasure set up or the module wide chests are missing
nType = TREASURE_TYPE_LOW;
}
if (nType == TREASURE_TYPE_JUNK) {
sContTag = sContJunk;
} else if (nType == TREASURE_TYPE_LOW) {
sContTag = sContLow;
} else if (nType == TREASURE_TYPE_MED) {
sContTag = sContMed;
} else if (nType == TREASURE_TYPE_HIGH) {
sContTag = sContHigh;
} else if (nType == TREASURE_TYPE_UNIQUE) {
sContTag = sContUniq;
} else {
// Invalid treasure type
return oCont;
}
oCont = GetNearestObjectByTag(sContTag);
if (!GetIsObjectValid(oCont)) {
// No area chest -- return the module-wide one
return CTG_GetModuleBaseContainer(nType);
}
return oCont;
}
// Get the module-wide base container of the appropriate type.
// Possible values for nTreasureType:
// TREASURE_TYPE_LOW
// TREASURE_TYPE_MED
// TREASURE_TYPE_HIGH
// TREASURE_TYPE_UNIQUE
object CTG_GetModuleBaseContainer(int nTreasureType)
{
object oCont = OBJECT_INVALID;
string sContTag = "";
if (nTreasureType == TREASURE_TYPE_LOW) {
sContTag = sModContLow;
} else if (nTreasureType == TREASURE_TYPE_MED) {
sContTag = sModContMed;
} else if (nTreasureType == TREASURE_TYPE_HIGH) {
sContTag = sModContHigh;
} else if (nTreasureType == TREASURE_TYPE_UNIQUE) {
sContTag = sModContUniq;
}
else {
// Invalid treasure type
return oCont;
}
oCont = GetObjectByTag(sContTag);
return oCont;
}
// Generate treasure using default method.
// Not prototyped -- this function should not be used outside
// this library.
void CTG_CreateDefaultTreasure(int nTreasureType, object oAdventurer, object oCont)
{
// generate treasure using default method from nw_o2_coninclude
if (nTreasureType == TREASURE_TYPE_LOW) {
GenerateLowTreasure(oAdventurer, oCont);
} else if (nTreasureType == TREASURE_TYPE_MED) {
GenerateMediumTreasure(oAdventurer, oCont);
} else if (nTreasureType == TREASURE_TYPE_HIGH) {
GenerateHighTreasure(oAdventurer, oCont);
} else if (nTreasureType == TREASURE_TYPE_UNIQUE) {
GenerateBossTreasure(oAdventurer, oCont);
}
}
// Get the specified item out of the given base container's inventory
object CTG_GetTreasureItem(object oBaseCont, int nItemNum)
{
if (!GetIsObjectValid(oBaseCont)) {return OBJECT_INVALID;}
// initialize the container -- this will automatically
// only happen once.
CTG_InitContainer(oBaseCont);
// Refs to the items are stored on the container itself
string sVar = sTreasureItemVarname + IntToString(nItemNum);
object oItem = GetLocalObject(oBaseCont, sVar);
return oItem;
}
// Starting from the specified item position, return the first
// item that matches one of the three base types.
// If nBaseType1 is passed in as invalid, NO TYPE CHECKING WILL BE DONE.
// nBaseType1 may also be passed in as a special custom type:
// TREASURE_BASE_TYPE_WEAPON (for any weapon type)
// TREASURE_BASE_TYPE_WEAPON_NOAMMO (for any weapon but ammunition)
// TREASURE_BASE_TYPE_WEAPON_RANGED (for any ranged weapon)
// TREASURE_BASE_TYPE_WEAPON_MELEE (for any melee weapon)
// TREASURE_BASE_TYPE_ARMOR (for armor, shields)
// TREASURE_BASE_TYPE_CLOTHING (for belts, boots, bracers,
// cloaks, helms, gloves)
object CTG_GetSpecificBaseTypeTreasureItem(object oBaseCont,
int nItemNum,
int nBaseType1=BASE_ITEM_INVALID,
int nBaseType2=BASE_ITEM_INVALID,
int nBaseType3=BASE_ITEM_INVALID)
{
if (!GetIsObjectValid(oBaseCont)) {return OBJECT_INVALID;}
// initialize the container -- this will automatically
// only happen once.
CTG_InitContainer(oBaseCont);
int nRollOverNum = CTG_GetNumItemsInBaseContainer(oBaseCont);
// If there are no items in the container, no chance of finding a matching one!
if (nRollOverNum == 0) return OBJECT_INVALID;
int i;
string sVar;
int nItemBaseType;
int nLooped = 0;
for (i=nItemNum; i != nItemNum || !nLooped ; i++) {
// The base type of each item is stored on the container itself
sVar = sBaseTypeVarname + IntToString(i);
nItemBaseType = GetLocalInt(oBaseCont, sVar);
// Check to see if the type matches our desired type.
if (
// Check for a weapon
(nBaseType1 == TREASURE_BASE_TYPE_WEAPON
&&
CTG_GetIsWeapon(nItemBaseType))
||
// non-ammo weapon
(nBaseType1 == TREASURE_BASE_TYPE_WEAPON_NOAMMO
&&
CTG_GetIsWeaponNoammo(nItemBaseType))
||
// ranged weapon
(nBaseType1 == TREASURE_BASE_TYPE_WEAPON_RANGED
&&
CTG_GetIsRangedWeapon(nItemBaseType))
||
// melee weapon
(nBaseType1 == TREASURE_BASE_TYPE_WEAPON_MELEE
&&
CTG_GetIsMeleeWeapon(nItemBaseType))
||
// armor
(nBaseType1 == TREASURE_BASE_TYPE_ARMOR
&&
CTG_GetIsArmor(nItemBaseType))
||
// clothing
(nBaseType1 == TREASURE_BASE_TYPE_CLOTHING
&&
CTG_GetIsClothing(nItemBaseType))
||
// other specific item type
( CTG_GetIsBaseType(nItemBaseType,
nBaseType1,
nBaseType2,
nBaseType3))
) // end of if statement
{
// we found a matching item -- return it
return CTG_GetTreasureItem(oBaseCont, i);
}
// Handle the wrap-around case
if ( (i+1) == nRollOverNum ) {
// set i back to 0
i = -1;
nLooped = 1;
}
}
// No matching item was found -- return null
return OBJECT_INVALID;
}
// Test if treasure has been generated in the given object
int CTG_GetIsTreasureGenerated(object oCont)
{
return GetLocalInt(oCont, sTreasureGeneratedVarname);
}
// Set whether treasure has been generated
void CTG_SetIsTreasureGenerated(object oCont, int bGenerated=TRUE)
{
SetLocalInt(oCont, sTreasureGeneratedVarname, bGenerated);
}
// Create random treasure items of the appropriate type
// in the specified container. Should be called
// by a script on a treasure container.
//
// Possible values for nTreasureType:
// TREASURE_TYPE_LOW
// TREASURE_TYPE_MED
// TREASURE_TYPE_HIGH
// TREASURE_TYPE_UNIQUE
void CTG_CreateTreasure(int nTreasureType,
object oAdventurer,
object oCont=OBJECT_SELF)
{
// To avoid code duplication, this actually just uses the specific
// version and passes an invalid item type
CTG_CreateSpecificBaseTypeTreasure(nTreasureType, oAdventurer, oCont);
}
// Create treasure of the appropriate treasure level and matching one
// of up to three different base types in the specified container.
//
// Possible values for nTreasureType:
// TREASURE_TYPE_LOW
// TREASURE_TYPE_MED
// TREASURE_TYPE_HIGH
// TREASURE_TYPE_UNIQUE
//
// Possible values for nBaseType1/2/3: any BASE_ITEM_* constant.
// Can also use these special values:
// TREASURE_BASE_TYPE_WEAPON (for any weapon type)
// TREASURE_BASE_TYPE_WEAPON_NOAMMO (for any weapon but ammunition)
// TREASURE_BASE_TYPE_WEAPON_RANGED (for any ranged weapon)
// TREASURE_BASE_TYPE_WEAPON_MELEE (for any melee weapon)
// TREASURE_BASE_TYPE_ARMOR (for armor, shields)
// TREASURE_BASE_TYPE_CLOTHING (for belts, boots, bracers,
// cloaks, helms, gloves)
//
void CTG_CreateSpecificBaseTypeTreasure(int nTreasureType,
object oAdventurer,
object oCont,
int nBaseType1=BASE_ITEM_INVALID,
int nBaseType2=BASE_ITEM_INVALID,
int nBaseType3=BASE_ITEM_INVALID)
{
// Prevent duplicate treasure generation
if (CTG_GetIsTreasureGenerated(oCont)) {return;}
CTG_SetIsTreasureGenerated(oCont);
// Locate the base container
object oBaseCont = CTG_GetNearestBaseContainer(nTreasureType,
oCont);
string oTag = GetTag(oBaseCont);
// Make sure we have a valid base container
if (!GetIsObjectValid(oBaseCont)) {
// if not, generate treasure using default method
if (nBaseType1 == BASE_ITEM_BOOK
|| nBaseType1 == BASE_ITEM_SPELLSCROLL)
{
// Make book treasure
GenerateBookTreasure(oAdventurer, oCont);
} else {
// Generate default treasure
CTG_CreateDefaultTreasure(nTreasureType, oAdventurer, oCont);
}
return;
}
// Get the number of available items
int nItemsInBaseCont = CTG_GetNumItemsInBaseContainer(oBaseCont);
// Special case: unique treasure or artifact items
if (nTreasureType == TREASURE_TYPE_UNIQUE)
{
// only give one item and only give it once
int nRandom = Random(nItemsInBaseCont);
object oItem;
if (nBaseType1 == BASE_ITEM_INVALID) {
// we're not checking base types
oItem = CTG_GetTreasureItem(oBaseCont, nRandom);
} else {
oItem = CTG_GetSpecificBaseTypeTreasureItem(oBaseCont,
nRandom,
nBaseType1,
nBaseType2,
nBaseType3);
}
if (!GetIsObjectValid(oItem))
{
CTG_CreateDefaultTreasure(nTreasureType, oAdventurer, oCont);
}
else
{
// Copy the item
// CreateItemOnObject(GetResRef(oItem), oCont);
// * do an actual copy BK Feb 2003. Less chance of resref errors
CopyItem(oItem, oCont, TRUE);
SetPlotFlag(oItem, FALSE);
// Destroy the original
DestroyObject(oItem, 1.0);
}
return;
}
// Otherwise, we generate 1-3 items, possibly convert some
// to gold.
int nItems = CTG_GetNumItems();
int nItemsCreated = 0;
object oItem = OBJECT_INVALID;
// Keep track of items handed out to avoid dupes
object oItem1 = OBJECT_INVALID;
object oItem2 = OBJECT_INVALID;
// Random number -- position of item to hand out
int nRandom = 0;
while (nItemsCreated < nItems) {
nItemsCreated++;
if (nBaseType1 == BASE_ITEM_INVALID && CTG_IsItemGold() )
{
CTG_CreateGoldTreasure(nTreasureType, oAdventurer, oCont);
}
else
{
nRandom = Random(nItemsInBaseCont);
if (nBaseType1 == BASE_ITEM_INVALID)
{
// we're not checking base types
oItem = CTG_GetTreasureItem(oBaseCont, nRandom);
}
else
{
oItem = CTG_GetSpecificBaseTypeTreasureItem(oBaseCont,
nRandom,
nBaseType1,
nBaseType2,
nBaseType3);
}
if (!GetIsObjectValid(oItem))
{
// Ugh, no matching item found!
// Bad module designer, no cookie.
CTG_CreateDefaultTreasure(nTreasureType, oAdventurer, oCont);
}
else if ( nItemsCreated > 1 &&
(GetTag(oItem) == GetTag(oItem1) || GetTag(oItem) == GetTag(oItem2)) )
{
// Ugh, duplicate item. Make gold instead.
CTG_CreateGoldTreasure(nTreasureType, oAdventurer, oCont);
}
else
{
// Make the item
CopyItem(oItem, oCont, TRUE);
if (nItemsCreated == 1) {
oItem1 = oItem;
} else {
// if this is the third item, it doesn't matter
// anyway, so we might as well save the conditional.
oItem2 = oItem;
}
}
}
//Re-roll for the the next item. IE: If the above item was one from the high
//chest the next one might not be ;)
if (nTreasureType == TREASURE_TYPE_MONSTER)
{
oBaseCont = CTG_GetNearestBaseContainer(nTreasureType, oCont);
nItemsInBaseCont = CTG_GetNumItemsInBaseContainer(oBaseCont);
}
}
}
// Create gold treasure in the specified container.
void CTG_CreateGoldTreasure(int nTreasureType,
object oAdventurer,
object oCont=OBJECT_SELF)
{
// Just use the default generation scripts
CreateGold(oCont, oAdventurer, nTreasureType);
}
// Create treasure on an NPC.
// This function will typically be called from within the
// NPC's OnSpawn handler.
// Note that this defaults to TREASURE_TYPE_MONSTER, which uses
// the monster-specific treasure chests and falls back to low-
// level treasure if none exist.
void CTG_GenerateNPCTreasure(int nTreasureType=5, object oNPC=OBJECT_SELF)
{
// Locate the base container
object oBaseCont = CTG_GetNearestBaseContainer(nTreasureType,
oNPC);
// Make sure we have a valid base container
if (!GetIsObjectValid(oBaseCont)) {
// if not, generate treasure using default method from
// nw_o2_coninclude.
if (nTreasureType == TREASURE_TYPE_MONSTER)
GenerateNPCTreasure(TREASURE_TYPE_MED, oNPC);
else
GenerateNPCTreasure(nTreasureType, oNPC);
return;
}
// Now we determine whether we put treasure on the NPC
int nRacialType = GetRacialType(oNPC);
switch (nRacialType) {
case RACIAL_TYPE_ANIMAL:
case RACIAL_TYPE_BEAST:
case RACIAL_TYPE_MAGICAL_BEAST:
case RACIAL_TYPE_VERMIN:
// No treasure, sorry.
return;
}
if (nTreasureType == TREASURE_TYPE_MONSTER) {
if (d100() < BK_CHANCE_OF_N0_MONSTERTREASURE) {
return;
}
}
// Otherwise, generate as usual
CTG_CreateTreasure(nTreasureType, oNPC, oNPC);
}
/**********************************************************************
* Boring type-checking functions.
**********************************************************************/
// Check if the item's base type is of the given base type
int CTG_GetIsBaseType(int nItemBaseType,
int nBaseType1=BASE_ITEM_INVALID,
int nBaseType2=BASE_ITEM_INVALID,
int nBaseType3=BASE_ITEM_INVALID)
{
return ( (nItemBaseType != BASE_ITEM_INVALID)
&& (
nItemBaseType == nBaseType1
|| nItemBaseType == nBaseType2
|| nItemBaseType == nBaseType3) );
}
// Check if the item's base type is a weapon
int CTG_GetIsWeapon(int nItemBaseType)
{
return (
nItemBaseType == BASE_ITEM_ARROW
|| nItemBaseType == BASE_ITEM_BASTARDSWORD
|| nItemBaseType == BASE_ITEM_BATTLEAXE
|| nItemBaseType == BASE_ITEM_BOLT
|| nItemBaseType == BASE_ITEM_BULLET
|| nItemBaseType == BASE_ITEM_CBLUDGWEAPON
|| nItemBaseType == BASE_ITEM_CLUB
|| nItemBaseType == BASE_ITEM_CPIERCWEAPON
|| nItemBaseType == BASE_ITEM_CSLASHWEAPON
|| nItemBaseType == BASE_ITEM_CSLSHPRCWEAP
|| nItemBaseType == BASE_ITEM_DAGGER
|| nItemBaseType == BASE_ITEM_DART
|| nItemBaseType == BASE_ITEM_DIREMACE
|| nItemBaseType == BASE_ITEM_DOUBLEAXE
|| nItemBaseType == BASE_ITEM_GREATAXE
|| nItemBaseType == BASE_ITEM_GREATSWORD
|| nItemBaseType == BASE_ITEM_GRENADE
|| nItemBaseType == BASE_ITEM_HALBERD
|| nItemBaseType == BASE_ITEM_HANDAXE
|| nItemBaseType == BASE_ITEM_HEAVYCROSSBOW
|| nItemBaseType == BASE_ITEM_HEAVYFLAIL
|| nItemBaseType == BASE_ITEM_KAMA
|| nItemBaseType == BASE_ITEM_KATANA
|| nItemBaseType == BASE_ITEM_KUKRI
|| nItemBaseType == BASE_ITEM_LIGHTCROSSBOW
|| nItemBaseType == BASE_ITEM_LIGHTFLAIL
|| nItemBaseType == BASE_ITEM_LIGHTHAMMER
|| nItemBaseType == BASE_ITEM_LIGHTMACE
|| nItemBaseType == BASE_ITEM_LONGBOW
|| nItemBaseType == BASE_ITEM_LONGSWORD
|| nItemBaseType == BASE_ITEM_MORNINGSTAR
|| nItemBaseType == BASE_ITEM_QUARTERSTAFF
|| nItemBaseType == BASE_ITEM_RAPIER
|| nItemBaseType == BASE_ITEM_SCIMITAR
|| nItemBaseType == BASE_ITEM_SCYTHE
|| nItemBaseType == BASE_ITEM_SHORTBOW
|| nItemBaseType == BASE_ITEM_SHORTSPEAR
|| nItemBaseType == BASE_ITEM_SHORTSWORD
|| nItemBaseType == BASE_ITEM_SHURIKEN
|| nItemBaseType == BASE_ITEM_SICKLE
|| nItemBaseType == BASE_ITEM_SLING
|| nItemBaseType == BASE_ITEM_THROWINGAXE
|| nItemBaseType == BASE_ITEM_TWOBLADEDSWORD
|| nItemBaseType == BASE_ITEM_WARHAMMER);
}
// Check if the item's base type is a weapon but not ammunition
int CTG_GetIsWeaponNoammo(int nItemBaseType)
{
return ( CTG_GetIsWeapon(nItemBaseType)
&& (nItemBaseType != BASE_ITEM_ARROW
|| nItemBaseType != BASE_ITEM_BOLT
|| nItemBaseType != BASE_ITEM_BULLET)
);
}
// Check if the item's base type is a ranged weapon
int CTG_GetIsRangedWeapon(int nItemBaseType)
{
return (nItemBaseType == BASE_ITEM_DART
|| nItemBaseType == BASE_ITEM_GRENADE
|| nItemBaseType == BASE_ITEM_HEAVYCROSSBOW
|| nItemBaseType == BASE_ITEM_LIGHTCROSSBOW
|| nItemBaseType == BASE_ITEM_LONGBOW
|| nItemBaseType == BASE_ITEM_SHORTBOW
|| nItemBaseType == BASE_ITEM_SHURIKEN
|| nItemBaseType == BASE_ITEM_SLING
|| nItemBaseType == BASE_ITEM_THROWINGAXE);
}
// Check if the item's base type is a melee weapon
int CTG_GetIsMeleeWeapon(int nItemBaseType)
{
return (
nItemBaseType == BASE_ITEM_BASTARDSWORD
|| nItemBaseType == BASE_ITEM_BATTLEAXE
|| nItemBaseType == BASE_ITEM_CLUB
|| nItemBaseType == BASE_ITEM_DAGGER
|| nItemBaseType == BASE_ITEM_DIREMACE
|| nItemBaseType == BASE_ITEM_DOUBLEAXE
|| nItemBaseType == BASE_ITEM_GREATAXE
|| nItemBaseType == BASE_ITEM_GREATSWORD
|| nItemBaseType == BASE_ITEM_HALBERD
|| nItemBaseType == BASE_ITEM_HANDAXE
|| nItemBaseType == BASE_ITEM_HEAVYFLAIL
|| nItemBaseType == BASE_ITEM_KAMA
|| nItemBaseType == BASE_ITEM_KATANA
|| nItemBaseType == BASE_ITEM_KUKRI
|| nItemBaseType == BASE_ITEM_LIGHTFLAIL
|| nItemBaseType == BASE_ITEM_LIGHTHAMMER
|| nItemBaseType == BASE_ITEM_LIGHTMACE
|| nItemBaseType == BASE_ITEM_LONGSWORD
|| nItemBaseType == BASE_ITEM_MORNINGSTAR
|| nItemBaseType == BASE_ITEM_QUARTERSTAFF
|| nItemBaseType == BASE_ITEM_RAPIER
|| nItemBaseType == BASE_ITEM_SCIMITAR
|| nItemBaseType == BASE_ITEM_SCYTHE
|| nItemBaseType == BASE_ITEM_SHORTSPEAR
|| nItemBaseType == BASE_ITEM_SHORTSWORD
|| nItemBaseType == BASE_ITEM_SICKLE
|| nItemBaseType == BASE_ITEM_TWOBLADEDSWORD
|| nItemBaseType == BASE_ITEM_WARHAMMER);
}
// Check if the item's base type is armor
int CTG_GetIsArmor(int nItemBaseType)
{
return (nItemBaseType == BASE_ITEM_ARMOR
|| nItemBaseType == BASE_ITEM_LARGESHIELD
|| nItemBaseType == BASE_ITEM_SMALLSHIELD
|| nItemBaseType == BASE_ITEM_TOWERSHIELD);
}
// Check if the item's base type is clothing
int CTG_GetIsClothing(int nItemBaseType)
{
return (nItemBaseType == BASE_ITEM_BELT
|| nItemBaseType == BASE_ITEM_BOOTS
|| nItemBaseType == BASE_ITEM_BRACER
|| nItemBaseType == BASE_ITEM_CLOAK
|| nItemBaseType == BASE_ITEM_GLOVES);
}
// Tack on the appropriate racialtype suffix
string CTG_GetRacialtypeChestTag(string sBaseTag, object oSource)
{
string sCont = sBaseTag + "_";
switch (GetRacialType(oSource))
{
case RACIAL_TYPE_INVALID: return "";
case RACIAL_TYPE_ABERRATION: sCont = sCont + "ABERRATION"; break;
case RACIAL_TYPE_ANIMAL: sCont = sCont + "ANIMAL"; break;
case RACIAL_TYPE_BEAST: sCont = sCont + "BEAST"; break;
case RACIAL_TYPE_CONSTRUCT: sCont = sCont + "CONSTRUCT"; break;
case RACIAL_TYPE_DRAGON: sCont = sCont + "DRAGON"; break;
case RACIAL_TYPE_DWARF: sCont = sCont + "DWARF"; break;
case RACIAL_TYPE_ELEMENTAL: sCont = sCont + "ELEMENTAL"; break;
case RACIAL_TYPE_ELF: sCont = sCont + "ELF"; break;
case RACIAL_TYPE_FEY: sCont = sCont + "FEY"; break;
case RACIAL_TYPE_GIANT: sCont = sCont + "GIANT"; break;
case RACIAL_TYPE_GNOME: sCont = sCont + "GNOME"; break;
case RACIAL_TYPE_HALFELF: sCont = sCont + "HALFELF"; break;
case RACIAL_TYPE_HALFLING: sCont = sCont + "HALFLING"; break;
case RACIAL_TYPE_HALFORC: sCont = sCont + "HALFORC"; break;
case RACIAL_TYPE_HUMAN: sCont = sCont + "HUMAN"; break;
case RACIAL_TYPE_HUMANOID_GOBLINOID: sCont = sCont + "GOBLINOID"; break;
case RACIAL_TYPE_HUMANOID_MONSTROUS: sCont = sCont + "MONSTROUS"; break;
case RACIAL_TYPE_HUMANOID_ORC: sCont = sCont + "ORC"; break;
case RACIAL_TYPE_HUMANOID_REPTILIAN: sCont = sCont + "REPTILIAN"; break;
case RACIAL_TYPE_MAGICAL_BEAST: sCont = sCont + "MAGICAL_BEAST"; break;
case RACIAL_TYPE_OUTSIDER: sCont = sCont + "OUTSIDER"; break;
case RACIAL_TYPE_SHAPECHANGER: sCont = sCont + "SHAPECHANGER"; break;
case RACIAL_TYPE_UNDEAD: sCont = sCont + "UNDEAD"; break;
case RACIAL_TYPE_VERMIN: sCont = sCont + "VERMIN"; break;
}
return sCont;
}
//void main() {}