325 lines
7.6 KiB
Plaintext
325 lines
7.6 KiB
Plaintext
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Olander's AI
|
|
// oai_inc_eqweapon
|
|
// by Don Anderson
|
|
// dandersonru@msn.com
|
|
//
|
|
// Equip Appropriate Weaopns
|
|
// Originally Bioware
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "opw_inc_weapons"
|
|
#include "x0_i0_enemy"
|
|
|
|
/******************************************************************************/
|
|
//:: FUNCTION PROTOTYPES
|
|
|
|
//Unequips Left and Right Hands
|
|
void OAI_UnequipWeapons();
|
|
|
|
// Equip the appropriate weapons to face the target.
|
|
void OAI_EquipAppropriateWeapons(int nClearActions=TRUE);
|
|
|
|
//Equip Ranged Weapon
|
|
int OAI_EquipRanged();
|
|
|
|
// * returns true if out of ammo of currently equipped weapons
|
|
int OAI_IsOutOfAmmo();
|
|
|
|
//Equips the Stored Right Handed Melee
|
|
int OAI_EquipRHMelee();
|
|
|
|
//Equips the Left Handed Weapon or Shield
|
|
int OAI_EquipLHMelee();
|
|
|
|
//Chooses Weapons For Melee/Dual/Shield and Ranged
|
|
void OAI_ChooseWeapons();
|
|
|
|
// * checks to see if oUser has ambidexteriy and two weapon fighting
|
|
int OAI_WiseToDualWield(object oUser);
|
|
|
|
//This is just a wrapper around ActionAttack
|
|
//To make sure the creature equips weapons
|
|
void OAI_WrapperActionAttack(object oTarget);
|
|
|
|
|
|
//:: FUNCTION PROTOTYPES
|
|
/******************************************************************************/
|
|
|
|
/******************************************************************************/
|
|
//:: FUNCTIONS
|
|
|
|
void OAI_UnequipWeapons()
|
|
{
|
|
//Now We Unequip Melee Weapons and Shields
|
|
object oLHand = GetItemInSlot(INVENTORY_SLOT_LEFTHAND,OBJECT_SELF);
|
|
if(GetIsObjectValid(oLHand)) AssignCommand(OBJECT_SELF, ActionUnequipItem(oLHand));
|
|
|
|
object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,OBJECT_SELF);
|
|
int nMelee = IsMeleeWeapon(oWeapon);
|
|
if(nMelee == TRUE) AssignCommand(OBJECT_SELF, ActionUnequipItem(oWeapon));
|
|
}
|
|
|
|
void OAI_EquipAppropriateWeapons(int nClearActions=TRUE)
|
|
{
|
|
object oSelf = OBJECT_SELF;
|
|
|
|
int nEmptyHanded = FALSE;
|
|
int nAlreadyClearedActions = FALSE;
|
|
|
|
//Set Up Weapons
|
|
int nHPW = GetLocalInt(oSelf,"OAI_HPW");
|
|
if(nHPW == FALSE)
|
|
{
|
|
OAI_ChooseWeapons();
|
|
SetLocalInt(oSelf,"OAI_HPW",TRUE);
|
|
}
|
|
|
|
object oRightHand = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND);
|
|
object oLeftHand = GetItemInSlot(INVENTORY_SLOT_LEFTHAND);
|
|
object oGloves = GetItemInSlot(INVENTORY_SLOT_ARMS);
|
|
|
|
if(!GetIsObjectValid(oRightHand)) nEmptyHanded = TRUE;
|
|
|
|
//Determine Enemy Distance
|
|
object oEnemy = GetLocalObject(OBJECT_SELF,"OAI_ATTACK_TARGET");
|
|
if(!GetIsObjectValid(oEnemy)) oEnemy = GetNearestPerceivedEnemy();
|
|
float fDist = GetDistanceBetween(OBJECT_SELF, oEnemy);
|
|
|
|
//Ranged Attack
|
|
int nIsWieldingRanged = FALSE;
|
|
nIsWieldingRanged = IsRangedWeapon(oRightHand);
|
|
|
|
//Not Wielding a Ranged Weapon and At Ranged Distance
|
|
if(!nIsWieldingRanged && fDist > 5.0)
|
|
{
|
|
if(nClearActions && !nAlreadyClearedActions)
|
|
{
|
|
ClearAllActions();
|
|
nAlreadyClearedActions = TRUE;
|
|
}
|
|
|
|
//Equip a Ranged
|
|
if(OAI_EquipRanged() && !OAI_IsOutOfAmmo()) return;
|
|
}
|
|
|
|
//Not Wielding a Ranged Weapon and At Melee Distance
|
|
else if(!nIsWieldingRanged && fDist <= 5.0)
|
|
{
|
|
//Point Blank Shot Feat
|
|
int nPBS = FALSE;
|
|
if(GetHasFeat(FEAT_POINT_BLANK_SHOT) == TRUE)
|
|
{
|
|
nPBS = TRUE;
|
|
}
|
|
|
|
//Close Ranged Combat
|
|
if(nPBS == TRUE)
|
|
{
|
|
if(nClearActions && !nAlreadyClearedActions)
|
|
{
|
|
ClearAllActions();
|
|
nAlreadyClearedActions = TRUE;
|
|
}
|
|
|
|
//Equip a Ranged
|
|
if(OAI_EquipRanged() && !OAI_IsOutOfAmmo()) return;
|
|
}
|
|
}
|
|
|
|
//Melee Attack
|
|
else
|
|
{
|
|
//Dual Wield
|
|
//Are we already dual-wielding? Don't do anything.
|
|
if(IsSingleHandedMeleeWeapon(oRightHand) && IsSingleHandedMeleeWeapon(oLeftHand)) return;
|
|
|
|
//Have the Dualing Feats
|
|
else if(OAI_WiseToDualWield(oSelf))
|
|
{
|
|
if(nClearActions && !nAlreadyClearedActions)
|
|
{
|
|
ClearAllActions();
|
|
nAlreadyClearedActions = TRUE;
|
|
}
|
|
|
|
//Equips the Stored Right Handed Melee
|
|
if(OAI_EquipRHMelee()) {}
|
|
|
|
//Equips the Left Handed Weapon or Shield
|
|
if(OAI_EquipLHMelee()) {}
|
|
}
|
|
|
|
//Holding a Single Weapon Already
|
|
else if(IsSingleHandedMeleeWeapon(oRightHand)) return;
|
|
|
|
//Right Hand and Shield
|
|
else
|
|
{
|
|
if(nClearActions && !nAlreadyClearedActions)
|
|
{
|
|
ClearAllActions();
|
|
nAlreadyClearedActions = TRUE;
|
|
}
|
|
|
|
//Equips the Stored Right Handed Melee
|
|
if(OAI_EquipRHMelee()) {}
|
|
|
|
//Equips the Left Handed Weapon or Shield
|
|
if(OAI_EquipLHMelee() && GetHasFeat(FEAT_SHIELD_PROFICIENCY,oSelf)) {}
|
|
}
|
|
}
|
|
}
|
|
|
|
int OAI_EquipRanged()
|
|
{
|
|
object oItem = GetLocalObject(OBJECT_SELF, "OAI_RANGED");
|
|
if(oItem != OBJECT_INVALID)
|
|
{
|
|
ActionDoCommand(ActionEquipItem(oItem,INVENTORY_SLOT_RIGHTHAND));
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
int OAI_IsOutOfAmmo()
|
|
{
|
|
int nWeaponType = GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND));
|
|
object oAmmo = OBJECT_INVALID;
|
|
if (nWeaponType == BASE_ITEM_LONGBOW || nWeaponType == BASE_ITEM_SHORTBOW)
|
|
{
|
|
oAmmo = GetItemInSlot(INVENTORY_SLOT_ARROWS);
|
|
}
|
|
else if (nWeaponType == BASE_ITEM_LIGHTCROSSBOW || nWeaponType == BASE_ITEM_HEAVYCROSSBOW)
|
|
{
|
|
oAmmo = GetItemInSlot(INVENTORY_SLOT_BOLTS);
|
|
}
|
|
else if (nWeaponType == BASE_ITEM_SLING)
|
|
{
|
|
oAmmo = GetItemInSlot(INVENTORY_SLOT_BULLETS);
|
|
}
|
|
|
|
if (GetIsObjectValid(oAmmo) == FALSE)
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
int OAI_WiseToDualWield(object oUser)
|
|
{
|
|
if (GetHasFeat(FEAT_AMBIDEXTERITY, oUser) && GetHasFeat(FEAT_TWO_WEAPON_FIGHTING, oUser))
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
int OAI_EquipRHMelee()
|
|
{
|
|
object oItem = GetLocalObject(OBJECT_SELF, "OAI_RH_MELEE");
|
|
if(oItem != OBJECT_INVALID)
|
|
{
|
|
ActionDoCommand(ActionEquipItem(oItem,INVENTORY_SLOT_RIGHTHAND));
|
|
return FALSE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
int OAI_EquipLHMelee()
|
|
{
|
|
object oItem = GetLocalObject(OBJECT_SELF, "OAI_LH_MELEE");
|
|
if(oItem != OBJECT_INVALID)
|
|
{
|
|
ActionDoCommand(ActionEquipItem(oItem,INVENTORY_SLOT_RIGHTHAND));
|
|
return FALSE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
void OAI_ChooseWeapons()
|
|
{
|
|
object oSelf = OBJECT_SELF;
|
|
|
|
object oShield=OBJECT_INVALID;
|
|
object oLeft=OBJECT_INVALID;
|
|
object oRight=OBJECT_INVALID;
|
|
object oRanged=OBJECT_INVALID;
|
|
|
|
int nHaveShield = FALSE;
|
|
int nSingle = 0;
|
|
|
|
//Ranged Weapon First
|
|
oRanged = GetFirstItemInInventory(oSelf);
|
|
while(GetIsObjectValid(oRanged))
|
|
{
|
|
//Both Medium and Light
|
|
if(IsRangedWeapon(oRanged))
|
|
{
|
|
nSingle++;
|
|
if(nSingle == 1)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
oRanged = GetNextItemInInventory(oSelf);
|
|
}
|
|
|
|
//Ranged Weapon
|
|
if(GetIsObjectValid(oRanged))
|
|
{
|
|
SetLocalObject(OBJECT_SELF, "OAI_RANGED", oRanged);
|
|
}
|
|
|
|
//Weapons and Shields
|
|
nSingle = 0;
|
|
object oItem = GetFirstItemInInventory(oSelf);
|
|
while(GetIsObjectValid(oItem))
|
|
{
|
|
//Both Medium and Light
|
|
if(IsSingleHandedMeleeWeapon(oItem))
|
|
{
|
|
nSingle++;
|
|
if(nSingle == 1) oRight = oItem;
|
|
else if (nSingle == 2) oLeft = oItem;
|
|
else break;
|
|
}
|
|
else if(MatchShield(oItem))
|
|
{
|
|
nHaveShield = TRUE;
|
|
oShield = oItem;
|
|
}
|
|
oItem = GetNextItemInInventory(oSelf);
|
|
}
|
|
|
|
//Right Hand Weapon
|
|
if(GetIsObjectValid(oRight))
|
|
{
|
|
SetLocalObject(OBJECT_SELF, "OAI_RH_MELEE", oItem);
|
|
}
|
|
|
|
//Left Hand Shield
|
|
if(GetIsObjectValid(oShield)
|
|
&& nHaveShield
|
|
&& GetHasFeat(FEAT_SHIELD_PROFICIENCY,oSelf))
|
|
{
|
|
SetLocalObject(OBJECT_SELF, "OAI_LH_MELEE", oShield);
|
|
}
|
|
|
|
//Left Hand Weapon (Will Override Shield)
|
|
if(GetIsObjectValid(oLeft) && OAI_WiseToDualWield(OBJECT_SELF))
|
|
{
|
|
SetLocalObject(OBJECT_SELF, "OAI_LH_MELEE", oLeft);
|
|
}
|
|
}
|
|
|
|
void OAI_WrapperActionAttack(object oTarget)
|
|
{
|
|
OAI_EquipAppropriateWeapons();
|
|
ActionAttack(oTarget);
|
|
}
|
|
|
|
//void main(){}
|