(f2cce83a3) AI combat improvements: - Bots now find weapons that are inside the equipped containers (tool boxes). - Bots can now use any item as a weapon as long as there's a combat priority defined for the items. - Adjust the combat priorities a bit; the bots now prioritize welding tool and plasma cutter over wrench or toolbox.
This commit is contained in:
@@ -49,9 +49,7 @@ namespace Barotrauma
|
||||
public override bool ConcurrentObjectives => true;
|
||||
|
||||
private readonly AIObjectiveFindSafety findSafety;
|
||||
private readonly HashSet<RangedWeapon> rangedWeapons = new HashSet<RangedWeapon>();
|
||||
private readonly HashSet<MeleeWeapon> meleeWeapons = new HashSet<MeleeWeapon>();
|
||||
private readonly HashSet<Item> adHocWeapons = new HashSet<Item>();
|
||||
private readonly HashSet<ItemComponent> weapons = new HashSet<ItemComponent>();
|
||||
|
||||
private AIObjectiveContainItem seekAmmunition;
|
||||
private AIObjectiveGoTo retreatObjective;
|
||||
@@ -162,7 +160,7 @@ namespace Barotrauma
|
||||
else if (!WeaponComponent.HasRequiredContainedItems(false))
|
||||
{
|
||||
// Seek ammunition only if cannot find a new weapon
|
||||
if (!Reload(true, () => GetWeapon() == null))
|
||||
if (!Reload(true, () => GetWeapon(out _) == null))
|
||||
{
|
||||
if (seekAmmunition != null && subObjectives.Contains(seekAmmunition))
|
||||
{
|
||||
@@ -177,11 +175,11 @@ namespace Barotrauma
|
||||
}
|
||||
if (Weapon == null)
|
||||
{
|
||||
Weapon = GetWeapon();
|
||||
Weapon = GetWeapon(out _weaponComponent);
|
||||
}
|
||||
if (Weapon == null)
|
||||
{
|
||||
Weapon = GetWeapon(ignoreRequiredItems: true);
|
||||
Weapon = GetWeapon(out _weaponComponent, ignoreRequiredItems: true);
|
||||
}
|
||||
Mode = Weapon == null ? CombatMode.Retreat : initialMode;
|
||||
return Weapon != null;
|
||||
@@ -205,30 +203,41 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private Item GetWeapon(bool ignoreRequiredItems = false)
|
||||
private Item GetWeapon(out ItemComponent weaponComponent, bool ignoreRequiredItems = false)
|
||||
{
|
||||
rangedWeapons.Clear();
|
||||
meleeWeapons.Clear();
|
||||
adHocWeapons.Clear();
|
||||
Item weapon = null;
|
||||
weapons.Clear();
|
||||
_weaponComponent = null;
|
||||
foreach (var item in character.Inventory.Items)
|
||||
{
|
||||
if (item == null) { continue; }
|
||||
SeekWeapons(item);
|
||||
if (item.OwnInventory != null)
|
||||
{
|
||||
item.OwnInventory.Items.ForEach(i => SeekWeapons(i));
|
||||
}
|
||||
}
|
||||
weaponComponent = weapons.OrderByDescending(w => w.CombatPriority).FirstOrDefault();
|
||||
if (weaponComponent == null) { return null; }
|
||||
if (weaponComponent.CombatPriority < 1) { return null; }
|
||||
return weaponComponent.Item;
|
||||
|
||||
void SeekWeapons(Item item)
|
||||
{
|
||||
if (item == null) { return; }
|
||||
foreach (var component in item.Components)
|
||||
{
|
||||
if (component is RangedWeapon rw)
|
||||
{
|
||||
if (ignoreRequiredItems || rw.HasRequiredContainedItems(false))
|
||||
{
|
||||
rangedWeapons.Add(rw);
|
||||
weapons.Add(rw);
|
||||
}
|
||||
}
|
||||
else if (component is MeleeWeapon mw)
|
||||
{
|
||||
if (ignoreRequiredItems || mw.HasRequiredContainedItems(false))
|
||||
{
|
||||
meleeWeapons.Add(mw);
|
||||
weapons.Add(mw);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -244,7 +253,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (ignoreRequiredItems || component.HasRequiredContainedItems(false))
|
||||
{
|
||||
adHocWeapons.Add(item);
|
||||
weapons.Add(component);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -253,21 +262,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
var rangedWeapon = rangedWeapons.OrderByDescending(w => w.CombatPriority).FirstOrDefault();
|
||||
var meleeWeapon = meleeWeapons.OrderByDescending(w => w.CombatPriority).FirstOrDefault();
|
||||
if (rangedWeapon != null)
|
||||
{
|
||||
weapon = rangedWeapon.Item;
|
||||
}
|
||||
else if (meleeWeapon != null)
|
||||
{
|
||||
weapon = meleeWeapon.Item;
|
||||
}
|
||||
if (weapon == null)
|
||||
{
|
||||
weapon = adHocWeapons.GetRandom(Rand.RandSync.Server);
|
||||
}
|
||||
return weapon;
|
||||
}
|
||||
|
||||
private void Unequip()
|
||||
|
||||
@@ -208,7 +208,13 @@ namespace Barotrauma.Items.Components
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// How useful the item is in combat? Used by AI to decide which item it should use as a weapon. For the sake of clarity, use a value between 0 and 100 (not enforced).
|
||||
/// </summary>
|
||||
[Serialize(0f, false)]
|
||||
public float CombatPriority { get; private set; }
|
||||
|
||||
public ItemComponent(Item item, XElement element)
|
||||
{
|
||||
this.item = item;
|
||||
@@ -539,6 +545,7 @@ namespace Barotrauma.Items.Components
|
||||
GameAnalyticsManager.AddErrorEventOnce("ItemComponent.DegreeOfSuccess:CharacterNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return 0.0f;
|
||||
}
|
||||
float average = skillSuccessSum / requiredSkills.Count;
|
||||
|
||||
float skillSuccessSum = 0.0f;
|
||||
for (int i = 0; i < requiredSkills.Count; i++)
|
||||
|
||||
Reference in New Issue
Block a user