Jaysyn904 0e9e2c6950 2025/07/18 Update
Added PEPS.
Full compile.
2025-07-18 12:13:13 -04:00

1244 lines
55 KiB
Plaintext

/*////////////////////////////////////////////////////////////////////////////////////////////////////
Script Name: 0i_items
Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
Include scripts for use with items.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
//#include "0i_main"
#include "0i_messages"
// Returns TRUE if oItem is a weapon.
int ai_GetIsWeapon(object oItem);
// Returns TRUE if oItem is a melee weapon.
int ai_GetIsMeleeWeapon(object oItem);
// Returns TRUE if oItem is a slashing weapon.
int ai_GetIsSlashingWeapon(object oItem);
// Returns TRUE if oItem is a piercing weapon.
int ai_GetIsPiercingWeapon(object oItem);
// Returns TRUE if oItem is a bludgeoning weapon.
int ai_GetIsBludgeoningWeapon(object oItem);
// Returns TRUE if oItem is an ammo.
int ai_GetIsAmmo(object oItem);
// Returns TRUE if oItem is a thrown weapon.
int ai_GetIsThrownWeapon(object oItem);
// Returns TRUE if oItem is able to be used single handed by oCreature.
int ai_GetIsSingleHandedWeapon(object oItem, object oCreature);
// Returns TRUE if oItem is a light weapon for oCreature.
int ai_GetIsLightWeapon(object oItem, object oCreature);
// Returns TRUE if oItem is able to be used two handed by oCreature.
int ai_GetIsTwoHandedWeapon(object oItem, object oCreature);
// Returns TRUE if oItem is a double weapon.
int ai_GetIsDoubleWeapon(object oItem);
// Returns TRUE if oCreature has a ranged weapon equiped and has ammo for it.
int ai_HasRangedWeaponWithAmmo(object oCreature);
// Returns TRUE if oItem is a ranged weapon.
int ai_GetIsRangeWeapon(object oItem);
// Returns the amount of damage the weapon oCreature is holding.
// nDamageAmount tells the function the amount of damage to return;
// 1 - Minimum, 2- Average, 3 Maximum.
// bMelee If it is not a melee weapon then return 0;
int ai_GetWeaponDamage(object oCreature, int nDamageAmount = 3, int bMelee = FALSE);
// Returns TRUE if oItem is a shield.
int ai_GetIsShield(object oItem);
// Returns the size of oItem using 1 = small to 6 = large.
int ai_GetItemSize(object oItem);
// Returns TRUE if the caller has a potion that is identified of nSpell.
int ai_CheckPotionIsIdentified(object oCreature, int nSpell);
// Returns an item from oCreature's inventory with sTag.
// bCheckEquiped will also look through the creatures equiped items.
// Returns OBJECT_INVALID if the items does not exist with sTag.
object ai_GetCreatureHasItem(object oCreature, string sTag, int bCheckEquiped = FALSE);
// Returns TRUE if oCreature can identify oItem based on the file SkillVsItemCost.2da
// Reports the findings to oPC unless oPC = OBJECT_INVALID.
// If the item can be identified by oCreature then it will be identified.
int ai_IdentifyItemVsKnowledge(object oCreature, object oItem, object oPC = OBJECT_INVALID);
// Identifies all items on oObject based on the file SkillVsItemCost.2da
// Reports the findings to oPC unless oPC = OBJECT_INVALID
// bIdentifyAll ignores the chart and does what it says!
void ai_IdentifyAllVsKnowledge(object oCreature, object oContainer, object oPC = OBJECT_INVALID);
// Will (Un)Identify all items on oCreature.
// If bIdentify is TRUE they will all be Identified, FALSE Unidentifies them.
void ai_SetIdentifyAllItems(object oCreature, int bIdentify = TRUE);
// Returns oWeapons attack bonus from either Enhancment or Attack bonus.
int ai_GetWeaponAtkBonus(object oWeapon);
// Returns oArmors armor bonus.
int ai_GetArmorBonus(object oArmor);
// Returns the maximum gold value that an item can have to be equiped.
int ai_GetMaxItemValueThatCanBeEquiped(int nLevel);
// Returns the minimum level that is required to equip this item.
int ai_GetMinimumEquipLevel(object oItem);
// Returns oCreatures total attack bonus with melee weapon (Mostly).
int ai_GetCreatureAttackBonus(object oCreature);
// Returns TRUE if oCreature can use oItem based on Class, Race, and Alignment
// restrictions. Also checks UseMagicDevice of oCreature.
int ai_CheckIfCanUseItem(object oCreature, object oItem);
// Returns TRUE if oCreature can use oItem due to feats.
int ai_GetIsProficientWith(object oCreature, object oItem);
// Gets the Average Damage on the weapon for Main and Off Hand to allow
// us to check which weapon is better for oCreature to equip.
// b2Handed set to TRUE returns only checks main avg damage.
// bOffHand set to TRUE returns the OffHand avg damage.
// if b2Handed & bOffHand are set to TRUE it returns main & offhand added together.
// if oOffWeapon is Set then it will return the Avg Damage assuming oItem is
// the Main weapon and oOffWeapon is in the Offhand.
float ai_GetMeleeWeaponAvgDmg(object oCreature, object oItem, int b2Handed = FALSE, int bOffHand = FALSE, object oOffWeapon = OBJECT_INVALID);
// Sets shield AC on the shield to allow us to check which shield is better
// for oCreature to equip.
int ai_SetShieldAC(object oCreature, object oItem);
// Returns TRUE if oItem has nItemPropertyType.
// nItemPropertySubType will not be used if its below 0.
int ai_GetHasItemProperty(object oItem, int nItemPropertyType, int nItemPropertySubType = -1);
// Returns the highest bonus Lock Picks needed to unlock nLockDC in oCreatures inventory.
object ai_GetBestPicks(object oCreature, int nLockDC);
// Removes all items from oCreature.
void ai_RemoveInventory(object oCreature);
// Copies all equiped and inventory items from oOldHenchman to oNewHenchman.
void ai_MoveInventory(object oOldHenchman, object oNewHenchman);
// Returns if oCreature is proficient with nBaseItem.
// PRC lets the creature use any weapon, but gives -4 penalty if not proficient.
int prc_IsProficient(object oCreature, int nBaseItem);
int ai_GetIsWeapon(object oItem)
{
int nType = GetBaseItemType(oItem);
int nWeaponType = StringToInt(Get2DAString("baseitems", "WeaponType", nType));
if(nWeaponType) return TRUE;
return FALSE;
}
int ai_GetIsMeleeWeapon(object oItem)
{
int nType = GetBaseItemType(oItem);
if(StringToInt(Get2DAString("baseitems", "WeaponType", nType)) > 0)
{
if(StringToInt(Get2DAString("baseitems", "RangedWeapon", nType)) == 0) return TRUE;
}
return FALSE;
}
int ai_GetIsSingleHandedWeapon(object oItem, object oCreature)
{
if(!ai_GetIsMeleeWeapon(oItem)) return FALSE;
int nBaseItemType = GetBaseItemType(oItem);
// Weapon Size in the baseitems.2da is 1 = Tiny, 2 = Small, 3 = Medium, 4 = Large.
int nWeaponSize = StringToInt(Get2DAString("baseitems", "WeaponSize", nBaseItemType));
// Creature size is 1 = Tiny, 2 = Small, 3 = Medium, 4 = Large.
int nCreatureSize = GetCreatureSize(oCreature);
return nWeaponSize <= nCreatureSize;
}
int ai_GetIsLightWeapon(object oItem, object oCreature)
{
if(!ai_GetIsMeleeWeapon(oItem)) return FALSE;
int nBaseItemType = GetBaseItemType(oItem);
// Weapon Size in the baseitems.2da is 1 = Tiny, 2 = Small, 3 = Medium, 4 = Large.
int nWeaponSize = StringToInt(Get2DAString("baseitems", "WeaponSize", nBaseItemType));
// Creature size is 1 = Tiny, 2 = Small, 3 = Medium, 4 = Large.
int nCreatureSize = GetCreatureSize(oCreature);
return nWeaponSize < nCreatureSize;
}
int ai_GetIsTwoHandedWeapon(object oItem, object oCreature)
{
if(!ai_GetIsMeleeWeapon(oItem)) return FALSE;
int nBaseItemType = GetBaseItemType(oItem);
// Weapon Size in the baseitems.2da is 1 = Tiny, 2 = Small, 3 = Medium, 4 = Large.
int nWeaponSize = StringToInt(Get2DAString("baseitems", "WeaponSize", nBaseItemType));
// Ranged weapons have a value greater than 0 in this field. So melee weapons have 0.
int nWeaponMelee = StringToInt(Get2DAString("baseitems", "RangedWeapon", nBaseItemType));
// Creature size is 1 = Tiny, 2 = Small, 3 = Medium, 4 = Large.
int nCreatureSize = GetCreatureSize(oCreature);
return (nWeaponMelee == 0 && nWeaponSize > nCreatureSize);
}
int ai_GetIsDoubleWeapon(object oItem)
{
int iType = GetBaseItemType(oItem);
switch(iType)
{
case BASE_ITEM_DIREMACE:
case BASE_ITEM_DOUBLEAXE:
case BASE_ITEM_TWOBLADEDSWORD: return TRUE;
}
return FALSE;
}
int ai_GetIsSlashingWeapon(object oItem)
{
int iBaseItemType = GetBaseItemType(oItem);
int iWeaponType = StringToInt(Get2DAString("baseitems", "WeaponType", iBaseItemType));
// Weapon Type in the baseitems.2da is 1 = Piercing, 2 = Bludgeoning, 3 = Slashing.
return (iWeaponType == 3);
}
int ai_GetIsPiercingWeapon(object oItem)
{
int iBaseItemType = GetBaseItemType(oItem);
int iWeaponType = StringToInt(Get2DAString("baseitems", "WeaponType", iBaseItemType));
// Weapon Type in the baseitems.2da is 1 = Piercing, 2 = Bludgeoning, 3 = Slashing.
return (iWeaponType == 1);
}
int ai_GetIsBludgeoningWeapon(object oItem)
{
int iBaseItemType = GetBaseItemType(oItem);
int iWeaponType = StringToInt(Get2DAString("baseitems", "WeaponType", iBaseItemType));
// Weapon Type in the baseitems.2da is 1 = Piercing, 2 = Bludgeoning, 3 = Slashing.
return (iWeaponType == 2);
}
int ai_GetIsAmmo(object oItem)
{
switch(GetBaseItemType(oItem))
{
case BASE_ITEM_ARROW: return TRUE;
case BASE_ITEM_BOLT: return TRUE;
case BASE_ITEM_BULLET: return TRUE;
}
return FALSE;
}
int ai_GetIsThrownWeapon(object oItem)
{
switch(GetBaseItemType(oItem))
{
case BASE_ITEM_DART: return TRUE;
case BASE_ITEM_SHURIKEN: return TRUE;
case BASE_ITEM_THROWINGAXE: return TRUE;
}
return FALSE;
}
int ai_HasRangedWeaponWithAmmo(object oCreature)
{
object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCreature);
if(!GetWeaponRanged(oWeapon)) return FALSE;
int nAmmoType, nWeaponType = GetBaseItemType(oWeapon);
object oAmmo = OBJECT_INVALID;
if(nWeaponType == BASE_ITEM_LONGBOW || nWeaponType == BASE_ITEM_SHORTBOW)
{
if(ai_GetHasItemProperty(oWeapon, ITEM_PROPERTY_UNLIMITED_AMMUNITION)) return TRUE;
if(GetItemInSlot(INVENTORY_SLOT_ARROWS, oCreature) != OBJECT_INVALID) return TRUE;
nAmmoType = BASE_ITEM_ARROW;
}
else if(nWeaponType == BASE_ITEM_LIGHTCROSSBOW || nWeaponType == BASE_ITEM_HEAVYCROSSBOW)
{
if(ai_GetHasItemProperty(oWeapon, ITEM_PROPERTY_UNLIMITED_AMMUNITION)) return TRUE;
if(GetItemInSlot(INVENTORY_SLOT_BOLTS, oCreature) != OBJECT_INVALID) return TRUE;
nAmmoType = BASE_ITEM_BOLT;
}
else if(nWeaponType == BASE_ITEM_SLING)
{
if(ai_GetHasItemProperty(oWeapon, ITEM_PROPERTY_UNLIMITED_AMMUNITION)) return TRUE;
if(GetItemInSlot(INVENTORY_SLOT_BULLETS, oCreature) != OBJECT_INVALID) return TRUE;
nAmmoType = BASE_ITEM_BULLET;
}
else if(nWeaponType == BASE_ITEM_THROWINGAXE) return TRUE;
else if(nWeaponType == BASE_ITEM_SHURIKEN) return TRUE;
else if(nWeaponType == BASE_ITEM_DART) return TRUE;
// They don't have any ammo in the slot, but do they have ammo in the inventory?
oAmmo = GetFirstItemInInventory(oCreature);
while(oAmmo != OBJECT_INVALID)
{
if(GetBaseItemType(oAmmo) == nAmmoType)
{
if(nAmmoType == BASE_ITEM_ARROW) ActionEquipItem(oAmmo, INVENTORY_SLOT_ARROWS);
else if(nAmmoType == BASE_ITEM_BOLT) ActionEquipItem(oAmmo, INVENTORY_SLOT_BOLTS);
else if(nAmmoType == BASE_ITEM_BULLET) ActionEquipItem(oAmmo, INVENTORY_SLOT_BULLETS);
return TRUE;
}
oAmmo = GetNextItemInInventory(oCreature);
}
//ai_Debug("0i_items", "254", "They are out of ammo!");
return FALSE;
}
int ai_GetIsRangeWeapon(object oItem)
{
switch(GetBaseItemType(oItem))
{
case BASE_ITEM_DART: return TRUE;
case BASE_ITEM_HEAVYCROSSBOW: return TRUE;
case BASE_ITEM_LIGHTCROSSBOW: return TRUE;
case BASE_ITEM_LONGBOW: return TRUE;
case BASE_ITEM_SHORTBOW: return TRUE;
case BASE_ITEM_SHURIKEN: return TRUE;
case BASE_ITEM_SLING: return TRUE;
case BASE_ITEM_THROWINGAXE: return TRUE;
}
return FALSE;
}
int ai_GetIsFinesseWeapon(object oCreature, object oItem)
{
switch(GetBaseItemType(oItem))
{
case BASE_ITEM_DAGGER: return TRUE;
case BASE_ITEM_HANDAXE: return TRUE;
case BASE_ITEM_KAMA: return TRUE;
case BASE_ITEM_KUKRI: return TRUE;
case BASE_ITEM_LIGHTHAMMER: return TRUE;
case BASE_ITEM_LIGHTMACE: return TRUE;
case BASE_ITEM_RAPIER:
{
if(GetCreatureSize(oCreature) > CREATURE_SIZE_SMALL) return TRUE;
return FALSE;
}
case BASE_ITEM_SHORTSWORD: return TRUE;
case BASE_ITEM_SICKLE: return TRUE;
case BASE_ITEM_WHIP: return TRUE;
}
return FALSE;
}
int ai_GetWeaponDamage(object oCreature, int nDamageAmount = 3, int bMelee = FALSE)
{
object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCreature);
if(bMelee && ai_GetIsRangeWeapon(oItem)) return 0;
int nWeaponDamage = GetLocalInt(oItem, "AI_WEAPON_DAMAGE");
if(!nWeaponDamage)
{
if(ai_GetIsMeleeWeapon(oItem))
{
nWeaponDamage = GetAbilityModifier(ABILITY_STRENGTH, oCreature);
if(ai_GetIsTwoHandedWeapon(oItem, oCreature)) nWeaponDamage += nWeaponDamage / 2;
}
int nWeaponDice = StringToInt(Get2DAString("baseitems", "NumDice", GetBaseItemType(oItem)));
int nWeaponDie = StringToInt(Get2DAString("baseitems", "DieToRoll", GetBaseItemType(oItem)));
if(nDamageAmount == 1)
{
nWeaponDamage += nWeaponDice;
}
else if(nDamageAmount == 2)
{
nWeaponDamage += nWeaponDice * nWeaponDie / 2;
}
else
{
nWeaponDamage += nWeaponDice * nWeaponDie;
}
SetLocalInt(oItem, "AI_WEAPON_DAMAGE", nWeaponDamage);
}
return nWeaponDamage;
}
int ai_GetIsShield(object oItem)
{
switch(GetBaseItemType(oItem))
{
case BASE_ITEM_SMALLSHIELD: return TRUE;
case BASE_ITEM_LARGESHIELD: return TRUE;
case BASE_ITEM_TOWERSHIELD: return TRUE;
}
return FALSE;
}
int ai_GetItemSize(object oItem)
{
int nBaseItemType = GetBaseItemType(oItem);
int nWidth = StringToInt(Get2DAString("baseitems", "InvSlotWidth", nBaseItemType));
int nHeight = StringToInt(Get2DAString("baseitems", "InvSlotHeight", nBaseItemType));
return nWidth + nHeight - 1;
}
int ai_CheckPotionIsIdentified(object oCreature, int nSpell)
{
int nPotionSpell;
itemproperty ipPotion;
object oPotion = GetFirstItemInInventory(oCreature);
while(oPotion != OBJECT_INVALID)
{
if(GetIdentified(oPotion))
{
ipPotion = GetFirstItemProperty(oPotion);
nPotionSpell = GetItemPropertySubType(ipPotion);
nPotionSpell = StringToInt(Get2DAString("iprp_spells", "SpellIndex", nPotionSpell));
//ai_Debug("0i_talents", "318", "Potion ID'ed? nSpell: " + IntToString(nSpell) + " nPotionSpell: " + IntToString(nPotionSpell));
if(nSpell == nPotionSpell) return TRUE;
}
oPotion = GetNextItemInInventory(oCreature);
}
return FALSE;
}
object ai_GetCreatureHasItem(object oCreature, string sTag, int bCheckEquiped = FALSE)
{
// Cycle through the creatures unequiped items.
object oItem = GetFirstItemInInventory(oCreature);
while(oItem != OBJECT_INVALID)
{
if(GetTag(oItem) == sTag) return oItem;
oItem = GetNextItemInInventory(oCreature);
}
// Should we check the creatures equiped items.
// If we have already found it then stop looking.
int nSlot = 0;
if(bCheckEquiped)
{
// Check all of the creatures slots(0 - 17).
while(nSlot <= 17)
{
oItem = GetItemInSlot(nSlot, oCreature);
if(GetTag(oItem) == sTag) return oItem;
nSlot ++;
}
}
return OBJECT_INVALID;
}
int ai_IdentifyItemVsKnowledge(object oCreature, object oItem, object oPC = OBJECT_INVALID)
{
if(GetIdentified(oItem)) return FALSE;
int nKnowledge = GetSkillRank(SKILL_LORE, oCreature);
int nItemValue; // gold value of item
string sBaseName;
string sMaxValue = Get2DAString("SkillVsItemCost", "DeviceCostMax", nKnowledge);
int nMaxValue = StringToInt(sMaxValue);
// * Handle overflow(November 2003 - BK)
if(sMaxValue == "") nMaxValue = 0;
// Setting TRUE to get the true value of the item.
SetIdentified(oItem, TRUE);
nItemValue = GetGoldPieceValue(oItem);
if(nMaxValue <= nItemValue)
{
SetIdentified(oItem, FALSE);
if(oPC != OBJECT_INVALID)
{
sBaseName = GetStringByStrRef(StringToInt(Get2DAString("baseitems", "name", GetBaseItemType(oItem))));
ai_SendMessages(GetName(oCreature) + " cannot identify " + sBaseName, AI_COLOR_RED, oPC);
}
}
else
{
if(oPC != OBJECT_INVALID) ai_SendMessages(GetName(oCreature) + " has identified " + GetName(oItem), AI_COLOR_GREEN, oPC);
return TRUE;
}
return FALSE;
}
void ai_IdentifyAllVsKnowledge(object oCreature, object oContainer, object oPC = OBJECT_INVALID)
{
// SkillVsItemCost 2da starts 1 at 0 ... go figure!
int nKnowledge = GetSkillRank(SKILL_LORE, oCreature) - 1;
int nItemValue; // gold value of item
string sBaseName;
string sMaxValue = Get2DAString("SkillVsItemCost", "DeviceCostMax", nKnowledge);
int nMaxValue = StringToInt(sMaxValue);
// * Handle overflow(November 2003 - BK)
if(sMaxValue == "") nMaxValue = 0;
object oItem = GetFirstItemInInventory(oContainer);
while(oItem != OBJECT_INVALID)
{
if(!GetIdentified(oItem))
{
// setting TRUE to get the true value of the item.
SetIdentified(oItem, TRUE);
nItemValue = GetGoldPieceValue(oItem);
if(nMaxValue < nItemValue)
{
SetIdentified(oItem, FALSE);
sBaseName = GetStringByStrRef(StringToInt(Get2DAString("baseitems", "name", GetBaseItemType(oItem))));
if(oPC != OBJECT_INVALID) ai_SendMessages(GetName(oCreature) + " cannot identify " + sBaseName, AI_COLOR_RED, oPC);
}
else if(oPC != OBJECT_INVALID) ai_SendMessages(GetName(oCreature) + " has identified " + GetName(oItem), AI_COLOR_GREEN, oPC);
}
oItem = GetNextItemInInventory(oContainer);
}
}
void ai_SetIdentifyAllItems(object oCreature, int bIdentify = TRUE)
{
object oItem = GetFirstItemInInventory(oCreature);
while(oItem != OBJECT_INVALID)
{
if(!GetIdentified(oItem)) SetIdentified(oItem, bIdentify);
oItem = GetNextItemInInventory(oCreature);
}
int nSlot;
oItem = GetItemInSlot(nSlot, oCreature);
while(nSlot < 11)
{
if(!GetIdentified(oItem)) SetIdentified(oItem, bIdentify);
oItem = GetItemInSlot(++nSlot, oCreature);
}
}
int ai_GetWeaponAtkBonus(object oWeapon)
{
int nCounter = 1, nPropertyType, nBonus;
// Get first property
itemproperty ipProperty = GetFirstItemProperty(oWeapon);
while(GetIsItemPropertyValid(ipProperty))
{
// Check to see if the property type matches.
nPropertyType = GetItemPropertyType(ipProperty);
if(nPropertyType == 6/*ITEMPROPERTY_ENHANCEMENT*/ ||
nPropertyType == 56/*ITEMPROPERTY_ATTACKBONUS*/)
{
nBonus += GetItemPropertyCostTableValue(ipProperty);
}
// Get the next property.
ipProperty = GetNextItemProperty(oWeapon);
}
//ai_Debug("0i_items", "438", GetName(oWeapon) + " attack bonus is " + IntToString(nBonus));
return nBonus;
}
int ai_GetArmorBonus(object oArmor)
{
int nTorsoValue = GetItemAppearance(oArmor, ITEM_APPR_TYPE_ARMOR_MODEL, ITEM_APPR_ARMOR_MODEL_TORSO);
//ai_Debug("0i_items", "444", "Armor Bonus: " + Get2DAString("parts_chest.2da", "ACBONUS", nTorsoValue));
return StringToInt(Get2DAString("parts_chest", "ACBONUS", nTorsoValue));
}
int ai_GetMaxItemValueThatCanBeEquiped(int nLevel)
{
return StringToInt(Get2DAString("itemvalue", "MAXSINGLEITEMVALUE", nLevel - 1));
}
int ai_GetMinimumEquipLevel(object oItem)
{
int nIndex, nUnIdentified;
if(!GetIdentified(oItem))
{
nUnIdentified = TRUE;
SetIdentified(oItem, TRUE);
}
int nGoldValue = GetGoldPieceValue(oItem);
if(nUnIdentified) SetIdentified(oItem, FALSE);
int n2daMaxRow = Get2DARowCount("itemvalue");
while(nIndex < n2daMaxRow)
{
if(nGoldValue <= StringToInt(Get2DAString("itemvalue", "MAXSINGLEITEMVALUE", nIndex)))
{
return nIndex + 1;
}
nIndex++;
}
return nIndex;
}
int ai_GetCreatureAttackBonus(object oCreature)
{
object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCreature);
int nAtkBonus = GetBaseAttackBonus(oCreature);
if((GetHasFeat(FEAT_WEAPON_FINESSE, oCreature) && ai_GetIsFinesseWeapon(oCreature, oWeapon)) ||
ai_GetIsRangeWeapon(oWeapon))
{
nAtkBonus += GetAbilityModifier(ABILITY_DEXTERITY, oCreature);
}
else nAtkBonus += GetAbilityModifier(ABILITY_STRENGTH, oCreature);
if(ai_GetIsMeleeWeapon(oWeapon)) nAtkBonus += ai_GetWeaponAtkBonus(oWeapon);
return nAtkBonus;
}
int ai_CheckUseMagicDevice(object oCreature, string sColumn, object oItem)
{
if(!GetLocalInt(GetModule(), AI_RULE_ALLOW_UMD)) return FALSE;
int nUMD = GetSkillRank(SKILL_USE_MAGIC_DEVICE, oCreature);
//ai_Debug("0i_talents", "1600", GetName(oCreature) + " is check UMD: " + IntToString(nUMD));
if(nUMD < 1) return FALSE;
int nDC, nIndex, nItemValue = GetGoldPieceValue(oItem);
while(nIndex < 55)
{
//ai_Debug("0i_talents", "1605", GetName(oItem) + " has a value of " +
// Get2DAString("skillvsitemcost", "DeviceCostMax", nIndex) +
// " nIndex: " + IntToString(nIndex));
if(nItemValue < StringToInt(Get2DAString("skillvsitemcost", "DeviceCostMax", nIndex)))
{
//ai_Debug("0i_talents", "1610", "nUMD >= " + Get2DAString("skillvsitemcost", sColumn, nIndex));
if(nUMD >= StringToInt(Get2DAString("skillvsitemcost", sColumn, nIndex))) return TRUE;
return FALSE;
}
nIndex++;
}
return FALSE;
}
int ai_CheckIfCanUseItem(object oCreature, object oItem)
{
int bAlign, bClass, bRace, bAlignLimit, bClassLimit, bRaceLimit;
int nIprpSubType, nItemPropertyType;
// Check to see if this item is limited to a specific alignment, class, or race.
int nAlign1 = GetAlignmentLawChaos(oCreature);
int nAlign2 = GetAlignmentGoodEvil(oCreature);
int nRace = GetRacialType(oCreature);
//ai_Debug("0i_items", "615", "nAlign1: " + IntToString(nAlign1) +
// " nAlign2: " + IntToString(nAlign2) + " nRace: " + IntToString(nRace));
itemproperty ipProp = GetFirstItemProperty(oItem);
while(GetIsItemPropertyValid(ipProp))
{
nItemPropertyType = GetItemPropertyType(ipProp);
//ai_Debug("0i_items", "620", "ItempropertyType(62/63/64/65): " + IntToString(nItemPropertyType));
if(nItemPropertyType == ITEM_PROPERTY_USE_LIMITATION_ALIGNMENT_GROUP)
{
bAlignLimit = TRUE;
// SubType is the group index for iprp_aligngrp.2da
nIprpSubType = GetItemPropertySubType(ipProp);
//ai_Debug("0i_items", "626", "nIprpSubType: " + IntToString(nIprpSubType));
if(nIprpSubType == nAlign1 || nIprpSubType == nAlign2) bAlign = TRUE;
}
else if(nItemPropertyType == ITEM_PROPERTY_USE_LIMITATION_SPECIFIC_ALIGNMENT)
{
bAlignLimit = TRUE;
// SubType is the alignment index for iprp_alignment.2da
nIprpSubType = GetItemPropertySubType(ipProp);
//ai_Debug("0i_items", "634", "nIprpSubType: " + IntToString(nIprpSubType));
if(nIprpSubType == 0 && nAlign1 == 2 && nAlign2 == 4) bAlign = TRUE;
else if(nIprpSubType == 1 && nAlign1 == 2 && nAlign2 == 1) bAlign = TRUE;
else if(nIprpSubType == 2 && nAlign1 == 2 && nAlign2 == 5) bAlign = TRUE;
else if(nIprpSubType == 3 && nAlign1 == 1 && nAlign2 == 4) bAlign = TRUE;
else if(nIprpSubType == 4 && nAlign1 == 1 && nAlign2 == 1) bAlign = TRUE;
else if(nIprpSubType == 5 && nAlign1 == 1 && nAlign2 == 5) bAlign = TRUE;
else if(nIprpSubType == 6 && nAlign1 == 3 && nAlign2 == 4) bAlign = TRUE;
else if(nIprpSubType == 7 && nAlign1 == 3 && nAlign2 == 1) bAlign = TRUE;
else if(nIprpSubType == 8 && nAlign1 == 3 && nAlign2 == 5) bAlign = TRUE;
}
else if(nItemPropertyType == ITEM_PROPERTY_USE_LIMITATION_CLASS)
{
bClassLimit = TRUE;
// SubType is the class index for classes.2da
nIprpSubType = GetItemPropertySubType(ipProp);
//ai_Debug("0i_items", "650", "nIprpSubType: " + IntToString(nIprpSubType));
int nClassPosition = 1;
int nClass = GetClassByPosition(nClassPosition, oCreature);
while(nClassPosition <= AI_MAX_CLASSES_PER_CHARACTER)
{
if(nIprpSubType == nClass) bClass = TRUE;
nClass = GetClassByPosition(++nClassPosition, oCreature);
}
}
else if(nItemPropertyType == ITEM_PROPERTY_USE_LIMITATION_RACIAL_TYPE)
{
bRaceLimit = TRUE;
// SubType is the race index for racialtypes.2da
nIprpSubType = GetItemPropertySubType(ipProp);
//ai_Debug("0i_items", "664", "nIprpSubType: " + IntToString(nIprpSubType));
if(nIprpSubType == nRace) bRace = TRUE;
}
ipProp = GetNextItemProperty(oItem);
}
//ai_Debug("0i_items", "669", "bAlignLimit: " + IntToString(bAlignLimit) + " bAlign: " + IntToString(bAlign) +
// " bClassLimit: " + IntToString(bClassLimit) + " bClass: " + IntToString(bClass) +
// " bRaceLimit: " + IntToString(bRaceLimit) + " bRace: " + IntToString(bRace));
if(bClassLimit && !bClass && !ai_CheckUseMagicDevice(oCreature, "SkillReq_Class", oItem)) return FALSE;
if(bRaceLimit && !bRace && !ai_CheckUseMagicDevice(oCreature, "SkillReq_Race", oItem)) return FALSE;
if(bAlignLimit && !bAlign && !ai_CheckUseMagicDevice(oCreature, "SkillReq_Align", oItem)) return FALSE;
return TRUE;
}
int ai_GetIsProficientWith(object oCreature, object oItem)
{
int nWeaponType = GetBaseItemType(oItem);
// In the PRC you can equip any weapon.
if(GetLocalInt(GetModule(), AI_USING_PRC)) return TRUE;
int nFeat = StringToInt(Get2DAString("baseitems", "ReqFeat0", nWeaponType));
// If it is 0 then it doesn't require a feat or we are at the end of the
// feat requirements.
if(nFeat == 0) return TRUE;
if(GetHasFeat(nFeat, oCreature)) return TRUE;
nFeat = StringToInt(Get2DAString("baseitems", "ReqFeat1", nWeaponType));
if(nFeat == 0) return FALSE;
if(GetHasFeat(nFeat, oCreature)) return TRUE;
nFeat = StringToInt(Get2DAString("baseitems", "ReqFeat2", nWeaponType));
if(nFeat == 0) return FALSE;
if(GetHasFeat(nFeat, oCreature)) return TRUE;
nFeat = StringToInt(Get2DAString("baseitems", "ReqFeat3", nWeaponType));
if(nFeat == 0) return FALSE;
if(GetHasFeat(nFeat, oCreature)) return TRUE;
nFeat = StringToInt(Get2DAString("baseitems", "ReqFeat4", nWeaponType));
if(nFeat == 0) return FALSE;
if(GetHasFeat(nFeat, oCreature)) return TRUE;
return FALSE;
}
float ai_GetMeleeWeaponAvgDmg(object oCreature, object oItem, int b2Handed = FALSE, int bOffHand = FALSE, object oOffWeapon = OBJECT_INVALID)
{
// Has this weapon already been calculated for this creature?
if(oCreature == GetLocalObject(oItem, "AI_CREATURE_POSSESSION"))
{
// Return the Main weapons Avg Damage while using a weapon in the off hand.
if(oOffWeapon != OBJECT_INVALID)
{
// We recalculate all OffWeapon avg damage unless its a double weapon.
if(oOffWeapon == oItem)
{
float fMain2WDmg = GetLocalFloat(oItem, "AI_MAIN_2W_HAND_AVG_DMG");
// If they passed that this is a 2handed weapon then return the total
// Avg Dmg for oItem. Used for double weapons.
if(b2Handed)
{
fMain2WDmg += ai_GetMeleeWeaponAvgDmg(oCreature, oItem, FALSE, TRUE);
}
if(AI_DEBUG) ai_Debug("0i_items", "611", GetName(oItem) + " avg dmg with Offhand weapon (" + GetName(oOffWeapon) + ") " + FloatToString(fMain2WDmg, 0, 2));
return fMain2WDmg;
}
}
// Return the avg dmg for oItem assuming it is in the OffHand.
else if(bOffHand)
{
float fOffHandDmg = GetLocalFloat(oItem, "AI_OFFHAND_AVG_DMG");
if(AI_DEBUG) ai_Debug("0i_items", "618", GetName(oItem) + " fOffHandAvgDmg: " + FloatToString(fOffHandDmg, 0, 2));
return fOffHandDmg;
}
// If we get here then Return the avg dmg for oItem assuming its in the main hand.
else
{
float fMainDmg = GetLocalFloat(oItem, "AI_AVG_DMG");
if(AI_DEBUG)ai_Debug("0i_items", "623", GetName(oItem) + " fMainDmg: " + FloatToString(fMainDmg, 0, 2));
return fMainDmg;
}
}
// Set the creature to this item that we are calculationg the avg damages for.
SetLocalObject(oItem, "AI_CREATURE_POSSESSION", oCreature);
int nItemType = GetBaseItemType(oItem);
// Figure average damage for one attack, or two with two weapons.
// We are keeping it simple to reduce time and checks.
// Get the weapons base stats.
int nMinDmg = StringToInt(Get2DAString("baseitems", "NumDice", nItemType));
int nMaxDmg = nMinDmg * StringToInt(Get2DAString("baseitems", "DieToRoll", nItemType));
int nThreat = StringToInt(Get2DAString("baseitems", "CritThreat", nItemType));
int nMultiplier = StringToInt(Get2DAString("baseitems", "CritHitMult", nItemType));
int nIndex, nBonusMinDmg, nBonusMaxDmg, nItemPropertyType, nNumDice;
// We set ToHit to 10 for a 50% chance to hit without modifiers.
float fCritBonusDmg, fToHit = 10.0;
if(GetLocalInt(GetModule(), AI_USING_PRC))
{
if(!prc_IsProficient(oCreature, nItemType)) fToHit -= 4.0;
}
// Check oCreature's feats.
if(GetHasFeat(FEAT_WEAPON_FINESSE, oCreature) &&
ai_GetIsLightWeapon(oItem, oCreature))
{
// Add Dexterity modifier to the Attack bonus.
nIndex = GetAbilityModifier(ABILITY_DEXTERITY, oCreature);
}
else
{
// Add Strength modifier to the attack bonus.
nIndex = GetAbilityModifier(ABILITY_STRENGTH, oCreature);
// Add 1/2 strength modifier to damage for 2handed weapons, but not Double weapons.
if(b2Handed && !bOffHand)
{
nMinDmg += nIndex / 2;
nMaxDmg += nIndex / 2;
}
}
fToHit += nIndex;
if(GetHasFeat(StringToInt(Get2DAString("baseitems", "WeaponFocusFeat", nItemType)), oCreature, TRUE))
{
fToHit += 1.0;
if(GetHasFeat(StringToInt(Get2DAString("baseitems", "WeaponSpecializationFeat", nItemType)), oCreature, TRUE))
{
nMinDmg += 2;
nMaxDmg += 2;
}
if(GetHasFeat(StringToInt(Get2DAString("baseitems", "EpicWeaponFocusFeat", nItemType)), oCreature, TRUE))
{
fToHit += 2.0;
if(GetHasFeat(StringToInt(Get2DAString("baseitems", "EpicWeaponSpecializationFeat", nItemType)), oCreature, TRUE))
{
nMinDmg += 4;
nMaxDmg += 4;
}
}
}
if(GetHasFeat(StringToInt(Get2DAString("baseitems", "WeaponImprovedCriticalFeat", nItemType)), oCreature, TRUE))
{
nMultiplier += nMultiplier;
if(GetHasFeat(StringToInt(Get2DAString("baseitems", "EpicWeaponOverwhelmingCriticalFeat", nItemType)), oCreature, TRUE))
{
if(nMultiplier > 3) fCritBonusDmg = 10.5;
else if(nMultiplier == 3) fCritBonusDmg = 7.0;
else fCritBonusDmg = 3.5;
}
}
// Check oItem's properties.
itemproperty ipProperty = GetFirstItemProperty(oItem);
while(GetIsItemPropertyValid(ipProperty))
{
nItemPropertyType = GetItemPropertyType(ipProperty);
if(nItemPropertyType == ITEM_PROPERTY_ENHANCEMENT_BONUS)
{
nIndex = GetItemPropertyCostTableValue(ipProperty);
nBonusMinDmg += nIndex;
nBonusMaxDmg += nIndex;
fToHit += IntToFloat(nIndex);
}
else if(nItemPropertyType == ITEM_PROPERTY_DAMAGE_BONUS)
{
nIndex = GetItemPropertyCostTableValue(ipProperty);
nNumDice = StringToInt(Get2DAString("iprp_damagecost", "NumDice", nIndex));
nBonusMinDmg += nNumDice;
nBonusMaxDmg += nNumDice * StringToInt(Get2DAString("iprp_damagecost", "Die", nIndex));
}
else if(nItemPropertyType == ITEM_PROPERTY_ATTACK_BONUS)
{
nIndex = GetItemPropertyCostTableValue(ipProperty);
fToHit += IntToFloat(nIndex);
}
else if(nItemPropertyType == ITEM_PROPERTY_KEEN)
{
nIndex = GetItemPropertyCostTableValue(ipProperty);
nMultiplier += nMultiplier;
}
else if(nItemPropertyType == ITEM_PROPERTY_HASTE)
{
nIndex = GetItemPropertyCostTableValue(ipProperty);
nMinDmg += nMinDmg;
nMaxDmg += nMaxDmg;
nBonusMinDmg += nBonusMinDmg;
nBonusMaxDmg += nBonusMaxDmg;
nMultiplier += nMultiplier;
}
else if(nItemPropertyType == ITEM_PROPERTY_MASSIVE_CRITICALS)
{
nIndex = GetItemPropertyCostTableValue(ipProperty);
nNumDice = StringToInt(Get2DAString("iprp_damagecost", "NumDice", nIndex));
fCritBonusDmg += IntToFloat(nNumDice) + IntToFloat(nNumDice * StringToInt(Get2DAString("iprp_damagecost", "Die", nIndex))) / 2.0;
}
else if(nItemPropertyType == ITEM_PROPERTY_DECREASED_ENHANCEMENT_MODIFIER)
{
nIndex = GetItemPropertyCostTableValue(ipProperty);
nBonusMinDmg -= nIndex;
nBonusMaxDmg -= nIndex;
fToHit -= IntToFloat(nIndex);
}
else if(nItemPropertyType == ITEM_PROPERTY_DECREASED_ATTACK_MODIFIER)
{
nIndex = GetItemPropertyCostTableValue(ipProperty);
fToHit -= IntToFloat(nIndex);
}
else if(nItemPropertyType == ITEM_PROPERTY_DECREASED_DAMAGE)
{
nIndex = GetItemPropertyCostTableValue(ipProperty);
nBonusMinDmg -= nIndex;
nBonusMaxDmg -= nIndex;
}
else if(nItemPropertyType == ITEM_PROPERTY_NO_DAMAGE)
{
// A weapon always does a minimum of 1 pnt of damage.
nMinDmg = 1;
nMaxDmg = 1;
}
ipProperty = GetNextItemProperty(oItem);
}
float fAvgDmg = IntToFloat(nMinDmg + nMaxDmg + nBonusMinDmg + nBonusMaxDmg) / 2;
// Set value for Offhand chance to hit.
float fOffHandToHit = fToHit - 10.0;
float fOffHandAvgDmg = fAvgDmg;
// Set value for Main hand chance to hit with a weapon in Off hand.
float fMain2HandToHit = fToHit - 6.0;
float fMain2HandAvgDmg = fAvgDmg;
// Calculate the avg dmg for oItem used in the main hand with no Off hand weapon.
fToHit = fToHit / 20.0;
float fThreatChance = (IntToFloat(nThreat) / 20.0) * fToHit;
fAvgDmg = (fAvgDmg * fToHit) + ((fAvgDmg * IntToFloat(nMultiplier) + fCritBonusDmg) * fThreatChance);
SetLocalFloat(oItem, "AI_AVG_DMG", fAvgDmg);
if(AI_DEBUG) ai_Debug("0i_items", "768", GetName(oItem) + " fSingleAvgDmg: " + FloatToString(fAvgDmg, 0, 2));
if(!b2Handed || (b2Handed && oOffWeapon != OBJECT_INVALID))
{
// Calculate chance to hit based on two weapon feats and main hand vs off hand.
if(GetHasFeat(374/*Dual_Wield*/, oCreature))
{
if(ai_GetArmorBonus(GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature)) < 4)
{
fMain2HandToHit += 2.0;
fOffHandToHit += 6.0;
}
}
else
{
if(GetHasFeat(FEAT_AMBIDEXTERITY, oCreature)) fOffHandToHit += 4.0;
if(GetHasFeat(FEAT_TWO_WEAPON_FIGHTING, oCreature))
{
fMain2HandToHit += 2.0;
fOffHandToHit += 2.0;
}
}
if(ai_GetIsLightWeapon(oItem, oCreature)) fOffHandToHit += 2.0;
if(oOffWeapon != OBJECT_INVALID &&
(ai_GetIsLightWeapon(oOffWeapon, oCreature) || ai_GetIsDoubleWeapon(oItem)))
{
fMain2HandToHit += 2.0;
}
// Calculate the avg dmg for oItem used in the main hand with an off hand weapon.
fMain2HandToHit = fMain2HandToHit / 20.0;
fThreatChance = (IntToFloat(nThreat) / 20.0) * fMain2HandToHit;
fMain2HandAvgDmg = (fMain2HandAvgDmg * fMain2HandToHit) + ((fMain2HandAvgDmg * IntToFloat(nMultiplier) + fCritBonusDmg) * fThreatChance);
SetLocalFloat(oItem, "AI_MAIN_2W_HAND_AVG_DMG", fMain2HandAvgDmg);
if(AI_DEBUG) ai_Debug("0i_items", "768", GetName(oItem) + " fMain2HandAvgDmg: " + FloatToString(fMain2HandAvgDmg, 0, 2));
// Calculate the avg dmg for oItem used in the off hand.
fOffHandToHit = fOffHandToHit / 20.0;
fThreatChance = (IntToFloat(nThreat) / 20.0) * fOffHandToHit;
fOffHandAvgDmg = (fOffHandAvgDmg * fOffHandToHit) + ((fOffHandAvgDmg * IntToFloat(nMultiplier) + fCritBonusDmg) * fThreatChance);
SetLocalFloat(oItem, "AI_OFFHAND_AVG_DMG", fOffHandAvgDmg);
if(AI_DEBUG) ai_Debug("0i_items", "790", GetName(oItem) + " fOffHandAvgDmg: " + FloatToString(fOffHandAvgDmg, 0, 2));
// Return the correct value based on params passed.
if(oOffWeapon != OBJECT_INVALID)
{
// This is used only for double weapons! Must pass b2Handed = TRUE and
// oOffWeapon = the double weapon that was passes as oItem.
if(b2Handed) return fMain2HandAvgDmg + fOffHandAvgDmg;
return fMain2HandAvgDmg;
}
if(bOffHand) return fOffHandAvgDmg;
}
return fAvgDmg;
}
int ai_SetShieldAC(object oCreature, object oItem)
{
if(oCreature == GetLocalObject(oItem, "AI_CREATURE_POSSESSION"))
{
return GetLocalInt(oItem, "AI_SHIELD_AC");
}
// Set the creature who has this item for setting the power of.
SetLocalObject(oItem, "AI_CREATURE_POSSESSION", oCreature);
int nItemType = GetBaseItemType(oItem);
int nAC, nItemPropertyType;
if(nItemType == BASE_ITEM_SMALLSHIELD) nAC = 1;
else if(nItemType == BASE_ITEM_LARGESHIELD) nAC = 2;
else if(nItemType == BASE_ITEM_TOWERSHIELD) nAC = 3;
itemproperty ipProperty = GetFirstItemProperty(oItem);
while(GetIsItemPropertyValid(ipProperty))
{
nItemPropertyType = GetItemPropertyType(ipProperty);
if(nItemPropertyType == ITEM_PROPERTY_AC_BONUS)
{
nAC += GetItemPropertyCostTableValue(ipProperty);
}
else if(nItemPropertyType == ITEM_PROPERTY_DECREASED_AC)
{
nAC -= GetItemPropertyCostTableValue(ipProperty);
}
else if(nItemPropertyType == ITEM_PROPERTY_HASTE)
{
nAC += 4;
}
ipProperty = GetNextItemProperty(oItem);
}
SetLocalInt(oItem, "AI_SHIELD_AC", nAC);
if(AI_DEBUG) ai_Debug("0i_items", "718", GetName(oItem) + " nAC: " + IntToString(nAC));
return nAC;
}
int ai_GetHasItemProperty(object oItem, int nItemPropertyType, int nItemPropertySubType = -1)
{
itemproperty ipProperty = GetFirstItemProperty(oItem);
while(GetIsItemPropertyValid(ipProperty))
{
if(GetItemPropertyType(ipProperty) == nItemPropertyType)
{
if(nItemPropertySubType > -1)
{
if(GetItemPropertySubType(ipProperty) == nItemPropertySubType) return TRUE;
}
else return TRUE;
}
ipProperty = GetNextItemProperty(oItem);
}
return FALSE;
}
object ai_GetBestPicks(object oCreature, int nLockDC)
{
int nSkill = GetSkillRank(SKILL_OPEN_LOCK, oCreature);
int nBonus, nBestBonus = 99, nNeededBonus = nLockDC - nSkill - 20;
//ai_Debug("0i_items", "651", "nNeededBonus: " + IntToString(nNeededBonus));
// We don't need to use any picks!
if(nNeededBonus < 1) return OBJECT_INVALID;
object oBestItem = OBJECT_INVALID;
object oItem = GetFirstItemInInventory(oCreature);
while(oItem != OBJECT_INVALID)
{
if(GetBaseItemType(oItem) == BASE_ITEM_THIEVESTOOLS)
{
// Get the tools bonus.
itemproperty ipProperty = GetFirstItemProperty(oItem);
while(GetIsItemPropertyValid(ipProperty))
{
if(GetItemPropertyType(ipProperty) == ITEM_PROPERTY_THIEVES_TOOLS)
{
nBonus = GetItemPropertyCostTableValue(ipProperty);
if(nBonus >= nNeededBonus && nBonus < nBestBonus)
{
nBestBonus = nBonus;
oBestItem = oItem;
SetLocalInt(oBestItem, "AI_BONUS", nBestBonus);
break;
}
}
ipProperty = GetNextItemProperty(oItem);
}
}
oItem = GetNextItemInInventory(oCreature);
}
return oBestItem;
}
void ai_RemoveInventory(object oCreature)
{
object oItem = GetFirstItemInInventory(oCreature);
while(oItem != OBJECT_INVALID)
{
DestroyObject(oItem);
oItem = GetNextItemInInventory(oCreature);
}
int nIndex;
for(nIndex = 0; nIndex <= 13; nIndex++)
{
oItem = GetItemInSlot(nIndex, oCreature);
DestroyObject(oItem);
}
}
void ai_MoveInventory(object oOldHenchman, object oNewHenchman)
{
// Move all inventory items.
object oItem = GetFirstItemInInventory(oOldHenchman);
while(oItem != OBJECT_INVALID)
{
CopyItem(oItem, oNewHenchman, TRUE);
oItem = GetNextItemInInventory(oOldHenchman);
}
// Move all equiped items and equip on oNewHenchman.
int nIndex;
object oNewItem;
for(nIndex = 0; nIndex <= 13; nIndex++)
{
oItem = GetItemInSlot(nIndex, oOldHenchman);
if(oItem != OBJECT_INVALID)
{
oNewItem = CopyItem(oItem, oNewHenchman, TRUE);
if(!GetIdentified(oNewItem)) SetIdentified(oNewItem, TRUE);
ActionEquipItem(oNewItem, nIndex);
}
}
}
int prc_IsProficient(object oCreature, int nBaseItem)
{
switch(nBaseItem)
{
//special case: counts as simple for chitine
case BASE_ITEM_SHORTSWORD:
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oCreature)
|| GetHasFeat(3600/*FEAT_MINDBLADE*/, oCreature)
|| (GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature)
&& GetRacialType(oCreature) == 76/*RACIAL_TYPE_CHITINE*/)
|| GetHasFeat(7901/*FEAT_WEAPON_PROFICIENCY_SHORTSWORD*/, oCreature);
case BASE_ITEM_LONGSWORD:
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature)
|| GetHasFeat(3600/*FEAT_MINDBLADE*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_ELF, oCreature)
|| GetHasFeat(7902/*FEAT_WEAPON_PROFICIENCY_LONGSWORD*/, oCreature);
case BASE_ITEM_BATTLEAXE:
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature)
|| (GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature)
&& GetRacialType(oCreature) == 216/*RACIAL_TYPE_GNOLL*/)
|| GetHasFeat(7903/*FEAT_WEAPON_PROFICIENCY_BATTLEAXE*/, oCreature);
case BASE_ITEM_BASTARDSWORD:
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature)
|| GetHasFeat(3600/*FEAT_MINDBLADE*/, oCreature)
|| GetHasFeat(7904/*FEAT_WEAPON_PROFICIENCY_BASTARD_SWORD*/, oCreature);
case BASE_ITEM_LIGHTFLAIL:
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature)
|| GetHasFeat(7905/*FEAT_WEAPON_PROFICIENCY_LIGHT_FLAIL*/, oCreature);
case BASE_ITEM_WARHAMMER:
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature)
|| GetHasFeat(7906/*FEAT_WEAPON_PROFICIENCY_WARHAMMER*/, oCreature);
case BASE_ITEM_LONGBOW:
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_ELF, oCreature)
|| GetHasFeat(7907/*FEAT_WEAPON_PROFICIENCY_LONGBOW*/, oCreature);
case BASE_ITEM_LIGHTMACE:
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oCreature)
|| GetHasFeat(7908/*FEAT_WEAPON_PROFICIENCY_LIGHT_MACE*/, oCreature);
case BASE_ITEM_HALBERD:
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature)
|| GetHasFeat(7909/*FEAT_WEAPON_PROFICIENCY_HALBERD*/, oCreature);
case BASE_ITEM_SHORTBOW:
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_ELF, oCreature)
|| (GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature)
&& GetRacialType(oCreature) == 216/*RACIAL_TYPE_GNOLL*/)
|| GetHasFeat(7910/*FEAT_WEAPON_PROFICIENCY_SHORTBOW*/, oCreature);
case BASE_ITEM_TWOBLADEDSWORD:
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature)
|| GetHasFeat(7911/*FEAT_WEAPON_PROFICIENCY_TWO_BLADED_SWORD*/, oCreature);
case BASE_ITEM_GREATSWORD:
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature)
|| GetHasFeat(7912/*FEAT_WEAPON_PROFICIENCY_GREATSWORD*/, oCreature);
case BASE_ITEM_GREATAXE:
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature)
|| GetHasFeat(7913/*FEAT_WEAPON_PROFICIENCY_GREATAXE*/, oCreature);
case BASE_ITEM_DART:
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oCreature)
|| GetHasFeat(7914/*FEAT_WEAPON_PROFICIENCY_DART*/, oCreature);
case BASE_ITEM_DIREMACE:
return GetHasFeat(7915/*FEAT_WEAPON_PROFICIENCY_DIRE_MACE*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature);
case BASE_ITEM_DOUBLEAXE:
return GetHasFeat(7916/*FEAT_WEAPON_PROFICIENCY_DOUBLE_AXE*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature);
case BASE_ITEM_HEAVYFLAIL:
return GetHasFeat(7917/*FEAT_WEAPON_PROFICIENCY_HEAVY_FLAIL*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature);
case BASE_ITEM_LIGHTHAMMER:
return GetHasFeat(7918/*FEAT_WEAPON_PROFICIENCY_LIGHT_HAMMER*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature);
case BASE_ITEM_HANDAXE:
return GetHasFeat(7919/*FEAT_WEAPON_PROFICIENCY_HANDAXE*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_MONK, oCreature);
case BASE_ITEM_KAMA:
return GetHasFeat(7920/*FEAT_WEAPON_PROFICIENCY_KAMA*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_MONK, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature);
case BASE_ITEM_KATANA:
return GetHasFeat(7921/*FEAT_WEAPON_PROFICIENCY_KATANA*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature);
case BASE_ITEM_KUKRI:
return GetHasFeat(7922/*FEAT_WEAPON_PROFICIENCY_KUKRI*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature);
case BASE_ITEM_MORNINGSTAR:
return GetHasFeat(7923/*FEAT_WEAPON_PROFICIENCY_MORNINGSTAR*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oCreature);
case BASE_ITEM_QUARTERSTAFF:
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_WIZARD, oCreature);
case BASE_ITEM_RAPIER:
return GetHasFeat(7924/*FEAT_WEAPON_PROFICIENCY_RAPIER*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_ELF, oCreature);
case BASE_ITEM_SCIMITAR:
return GetHasFeat(7925/*FEAT_WEAPON_PROFICIENCY_SCIMITAR*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oCreature);
case BASE_ITEM_SCYTHE:
return GetHasFeat(7926/*FEAT_WEAPON_PROFICIENCY_SCYTHE*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature);
case BASE_ITEM_SHORTSPEAR:
return GetHasFeat(7927/*FEAT_WEAPON_PROFICIENCY_SHORTSPEAR*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oCreature);
case BASE_ITEM_SHURIKEN:
return GetHasFeat(7928/*FEAT_WEAPON_PROFICIENCY_SHURIKEN*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_MONK, oCreature);
case BASE_ITEM_SICKLE:
return GetHasFeat(7929/*FEAT_WEAPON_PROFICIENCY_SICKLE*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oCreature);
case BASE_ITEM_SLING:
return GetHasFeat(7930/*FEAT_WEAPON_PROFICIENCY_SLING*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_MONK, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oCreature);
case BASE_ITEM_THROWINGAXE:
return GetHasFeat(7931/*FEAT_WEAPON_PROFICIENCY_THROWING_AXE*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature)
|| GetHasFeat(3600/*FEAT_MINDBLADE*/, oCreature);
case BASE_ITEM_CSLASHWEAPON:
case BASE_ITEM_CPIERCWEAPON:
case BASE_ITEM_CBLUDGWEAPON:
case BASE_ITEM_CSLSHPRCWEAP:
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_CREATURE, oCreature);
case BASE_ITEM_TRIDENT:
return GetHasFeat(7932/*FEAT_WEAPON_PROFICIENCY_TRIDENT*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oCreature);
case 124://BASE_ITEM_DOUBLE_SCIMITAR:
return GetHasFeat(7948/*FEAT_WEAPON_PROFICIENCY_DOUBLE_SCIMITAR*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature);
case 119://BASE_ITEM_FALCHION:
return GetHasFeat(7943/*FEAT_WEAPON_PROFICIENCY_FALCHION*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature);
case 125://BASE_ITEM_GOAD:
return GetHasFeat(7949/*FEAT_WEAPON_PROFICIENCY_GOAD*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature);
case 122://BASE_ITEM_HEAVY_MACE:
return GetHasFeat(7946/*FEAT_WEAPON_PROFICIENCY_HEAVY_MACE*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oCreature);
case 115://BASE_ITEM_HEAVY_PICK:
return GetHasFeat(7939/*FEAT_WEAPON_PROFICIENCY_HEAVY_PICK*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature);
case 116://BASE_ITEM_LIGHT_PICK:
return GetHasFeat(7940/*FEAT_WEAPON_PROFICIENCY_LIGHT_PICK*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature);
case 121://BASE_ITEM_KATAR:
return GetHasFeat(7945/*FEAT_WEAPON_PROFICIENCY_KATAR*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature);
case 123://BASE_ITEM_MAUL:
return GetHasFeat(7947/*FEAT_WEAPON_PROFICIENCY_MAUL*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature);
case 118://BASE_ITEM_NUNCHAKU:
return GetHasFeat(7942/*FEAT_WEAPON_PROFICIENCY_NUNCHAKU*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_MONK, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature);
case 117://BASE_ITEM_SAI:
return GetHasFeat(7941/*FEAT_WEAPON_PROFICIENCY_SAI*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_MONK, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature);
case 120://BASE_ITEM_SAP:
return GetHasFeat(7944/*FEAT_WEAPON_PROFICIENCY_SAP*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature);
//special case: counts as martial for dwarves
case BASE_ITEM_DWARVENWARAXE:
return GetHasFeat(7933/*FEAT_WEAPON_PROFICIENCY_DWARVEN_WARAXE*/, oCreature)
|| (GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oCreature)
&& GetHasFeat(4710/*FEAT_DWARVEN*/, oCreature))
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature);
case BASE_ITEM_WHIP:
return GetHasFeat(7934/*FEAT_WEAPON_PROFICIENCY_WHIP*/, oCreature)
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oCreature);
}
return TRUE;
}
int ai_GetItemUses(object oItem, int nItemPropertySubType)
{
int nUses;
itemproperty ipProperty = GetFirstItemProperty(oItem);
while(GetIsItemPropertyValid(ipProperty))
{
if(GetItemPropertyType(ipProperty) == ITEM_PROPERTY_HEALERS_KIT) return GetItemStackSize(oItem);
if(nItemPropertySubType > -1)
{
if(GetItemPropertySubType(ipProperty) == nItemPropertySubType)
{
// Get how they use the item (charges or uses per day).
nUses = GetItemPropertyCostTableValue(ipProperty);
if(nUses == 1) return GetItemStackSize(oItem);
else if(nUses > 1 && nUses < 7) return GetItemCharges(oItem);
else if(nUses == 7 || nUses == 13) return 999;
else if(nUses > 7 && nUses < 13) return GetItemPropertyUsesPerDayRemaining(oItem, ipProperty);
}
}
else return TRUE;
ipProperty = GetNextItemProperty(oItem);
}
return FALSE;
}