Files
LuaCsForBarotraumaEP/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveLoadItems.cs
2023-05-10 15:07:17 +03:00

122 lines
5.4 KiB
C#

using Barotrauma.Extensions;
using Barotrauma.Items.Components;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
namespace Barotrauma
{
class AIObjectiveLoadItems : AIObjectiveLoop<Item>
{
public override Identifier Identifier { get; set; } = "load items".ToIdentifier();
protected override float IgnoreListClearInterval => 20.0f;
protected override bool ResetWhenClearingIgnoreList => false;
private ImmutableArray<Identifier> TargetContainerTags { get; }
private List<Item> TargetContainers { get; } = new List<Item>();
private ItemCondition TargetCondition { get; }
public enum ItemCondition
{
Empty,
Full
}
public AIObjectiveLoadItems(Character character, AIObjectiveManager objectiveManager, Identifier option, ImmutableArray<Identifier> containerTags, Item targetContainer = null, float priorityModifier = 1)
: base(character, objectiveManager, priorityModifier, option)
{
if ((containerTags == null || containerTags.None()) && targetContainer == null)
{
Abandon = true;
return;
}
else
{
TargetContainerTags = containerTags.ToImmutableArray();
}
if (targetContainer != null)
{
TargetContainers.Add(targetContainer);
}
else
{
foreach (Item item in Item.ItemList)
{
if (!OrderPrefab.TargetItemsMatchItem(TargetContainerTags, item)) { continue; }
TargetContainers.Add(item);
}
}
TargetCondition = option == "turretammo" ? ItemCondition.Empty : ItemCondition.Full;
}
protected override bool Filter(Item target)
{
//don't pass TargetContainerTags to the method (no need to filter by tags anymore, it's already done when populating TargetContainers)
if (!IsValidTarget(target, character, null, TargetCondition)) { return false; }
if (target.CurrentHull == null || target.CurrentHull.FireSources.Count > 0) { return false; }
if (Character.CharacterList.Any(c => c.CurrentHull == target.CurrentHull && !HumanAIController.IsFriendly(c) && HumanAIController.IsActive(c))) { return false; }
return true;
}
public static bool IsValidTarget(Item item, Character character, ImmutableArray<Identifier>? targetContainerTags = null, ItemCondition? targetCondition = null)
{
if (item == null || item.Removed) { return false; }
if (targetContainerTags.HasValue && !OrderPrefab.TargetItemsMatchItem(targetContainerTags.Value, item)) { return false; }
if ((item.GetComponent<ItemContainer>() is not ItemContainer container)) { return false; }
if (container.Inventory == null) { return false; }
if (targetCondition.HasValue && container.Inventory.IsFull() && container.Inventory.AllItems.None(i => ItemMatchesTargetCondition(i, targetCondition.Value))) { return false; }
if (!AIObjectiveCleanupItems.IsItemInsideValidSubmarine(item, character)) { return false; }
if (item.GetRootInventoryOwner() is Character owner && owner != character) { return false; }
if (item.IsClaimedByBallastFlora) { return false; }
if (!item.HasAccess(character)) { return false; }
// Ignore items that require power but don't have it
if (item.GetComponent<Powered>() is Powered powered && powered.PowerConsumption > 0 && powered.Voltage < powered.MinVoltage) { return false; }
return true;
}
public static bool ItemMatchesTargetCondition(Item item, ItemCondition targetCondition)
{
if(item == null) { return false; }
try
{
return targetCondition switch
{
ItemCondition.Empty => item.Condition <= 0.1f,
ItemCondition.Full => item.IsFullCondition,
_ => throw new NotImplementedException(),
};
}
catch (NotImplementedException)
{
#if DEBUG
DebugConsole.LogError($"Unexpected target condition \"{targetCondition}\" in AIObjectiveLoadItems.ItemMatchesTargetCondition");
#endif
return false;
}
}
protected override IEnumerable<Item> GetList() => TargetContainers;
protected override AIObjective ObjectiveConstructor(Item target)
=> new AIObjectiveLoadItem(target, TargetContainerTags, TargetCondition, Option, character, objectiveManager, PriorityModifier);
protected override void OnObjectiveCompleted(AIObjective objective, Item target)
=> HumanAIController.RemoveTargets<AIObjectiveLoadItems, Item>(character, target);
protected override float TargetEvaluation()
{
if (Targets.None()) { return 0; }
if (objectiveManager.IsOrder(this))
{
float prio = objectiveManager.GetOrderPriority(this);
if (subObjectives.All(so => so.SubObjectives.None() || so.Priority <= 0))
{
ForceWalk = true;
}
return prio;
}
return AIObjectiveManager.RunPriority - 0.5f;
}
}
}