1244 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			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;
 | |
| }
 | |
| 
 |