Files
LuaCsForBarotraumaEP/Barotrauma/BarotraumaServer/ServerSource/Traitors/Goals/GoalFindItem.cs
T
2022-02-26 02:43:01 +09:00

240 lines
10 KiB
C#

using Barotrauma.Items.Components;
using Barotrauma.Networking;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Barotrauma
{
partial class Traitor
{
public class GoalFindItem : HumanoidGoal
{
private readonly TraitorMission.CharacterFilter filter;
private readonly string identifier;
private readonly bool preferNew;
private readonly bool allowNew;
private readonly bool allowExisting;
private readonly HashSet<Identifier> allowedContainerIdentifiers = new HashSet<Identifier>();
private ItemPrefab targetPrefab;
private ItemPrefab containedPrefab;
private Item targetContainer;
private Item target;
private HashSet<Item> existingItems = new HashSet<Item>();
private string targetNameText;
private string targetContainerNameText;
private string targetHullNameText;
private float percentage;
private int spawnAmount = 1;
private const string itemContainerId = "toolbox";
public override IEnumerable<string> InfoTextKeys => base.InfoTextKeys.Concat(new string[] { "[identifier]", "[target]", "[targethullname]" });
public override IEnumerable<string> InfoTextValues(Traitor traitor) => base.InfoTextValues(traitor).Concat(new string[] { targetNameText ?? "", targetContainerNameText ?? "", targetHullNameText ?? "" });
public override bool IsCompleted => target != null && Traitors.Any(traitor => traitor.Character.HasItem(target));
public override bool CanBeCompleted(ICollection<Traitor> traitors)
{
if (!base.CanBeCompleted(traitors))
{
return false;
}
if (target == null)
{
var targetPrefabCandidate = FindItemPrefab(identifier);
return targetPrefabCandidate != null && FindTargetContainer(traitors, targetPrefabCandidate) != null;
}
if (target.Removed)
{
return false;
}
if (target.Submarine == null)
{
if (!(target.ParentInventory?.Owner is Character))
{
return false;
}
}
else
{
if (Traitors.All(traitor => target.Submarine.TeamID != traitor.Character.TeamID))
{
return false;
}
}
return true;
}
public override bool IsEnemy(Character character) => base.IsEnemy(character) || (target != null && target.FindParentInventory(inventory => inventory == character.Inventory) != null);
protected ItemPrefab FindItemPrefab(string identifier)
{
return (ItemPrefab)MapEntityPrefab.List.FirstOrDefault(prefab => prefab is ItemPrefab && prefab.Identifier == identifier);
}
protected Item FindRandomContainer(ICollection<Traitor> traitors, ItemPrefab targetPrefabCandidate, bool includeNew, bool includeExisting)
{
List<Item> suitableItems = new List<Item>();
foreach (Item item in Item.ItemList)
{
if (item.HiddenInGame || item.NonInteractable || item.NonPlayerTeamInteractable) { continue; }
if (item.Submarine == null || traitors.All(traitor => item.Submarine.TeamID != traitor.Character.TeamID))
{
continue;
}
if (item.GetComponent<ItemContainer>() != null && allowedContainerIdentifiers.Contains(((MapEntity)item).Prefab.Identifier))
{
if ((includeNew && !item.OwnInventory.IsFull()) || (includeExisting && item.OwnInventory.FindItemByIdentifier(targetPrefabCandidate.Identifier) != null))
{
suitableItems.Add(item);
}
}
}
if (suitableItems.Count == 0) { return null; }
return suitableItems[TraitorManager.RandomInt(suitableItems.Count)];
}
protected Item FindTargetContainer(ICollection<Traitor> traitors, ItemPrefab targetPrefabCandidate)
{
Item result = null;
if (preferNew)
{
result = FindRandomContainer(traitors, targetPrefabCandidate, true, false);
}
if (result == null)
{
result = FindRandomContainer(traitors, targetPrefabCandidate, allowNew, allowExisting);
}
if (result == null)
{
return null;
}
if (allowNew && !result.OwnInventory.IsFull())
{
return result;
}
if (allowExisting && result.OwnInventory.FindItemByIdentifier(targetPrefabCandidate.Identifier) != null)
{
return result;
}
return null;
}
public override bool Start(Traitor traitor)
{
if (!base.Start(traitor))
{
return false;
}
if (targetPrefab != null)
{
return true;
}
string targetPrefabTextId;
if (percentage > 0f)
{
spawnAmount = (int)Math.Floor(Character.CharacterList.FindAll(c => c.TeamID == traitor.Character.TeamID && c != traitor.Character && !c.IsDead && (filter == null || filter(c))).Count * percentage);
}
if (spawnAmount > 1 && allowNew)
{
containedPrefab = FindItemPrefab(identifier);
targetPrefab = FindItemPrefab(itemContainerId);
if (containedPrefab == null || targetPrefab == null)
{
return false;
}
targetPrefabTextId = containedPrefab.GetItemNameTextId();
}
else
{
spawnAmount = 1;
containedPrefab = null;
targetPrefab = FindItemPrefab(identifier);
if (targetPrefab == null)
{
return false;
}
targetPrefabTextId = targetPrefab.GetItemNameTextId();
}
targetNameText = targetPrefabTextId != null ? TextManager.FormatServerMessage(targetPrefabTextId) : targetPrefab.Name.Value;
targetContainer = FindTargetContainer(Traitors, targetPrefab);
if (targetContainer == null)
{
targetPrefab = null;
targetContainer = null;
return false;
}
var containerPrefabTextId = targetContainer.Prefab.GetItemNameTextId();
targetContainerNameText = containerPrefabTextId != null ? TextManager.FormatServerMessage(containerPrefabTextId) : targetContainer.Prefab.Name.Value;
var targetHullTextId = targetContainer.CurrentHull?.Prefab.GetHullNameTextId();
targetHullNameText = targetHullTextId != null ? TextManager.FormatServerMessage(targetHullTextId) : targetContainer?.CurrentHull?.DisplayName.Value ?? "";
if (allowNew && !targetContainer.OwnInventory.IsFull())
{
existingItems.Clear();
foreach (var item in targetContainer.OwnInventory.AllItems.Distinct())
{
existingItems.Add(item);
}
Entity.Spawner.AddItemToSpawnQueue(targetPrefab, targetContainer.OwnInventory, onSpawned: item =>
{
item.AddTag("traitormissionitem");
});
target = null;
}
else if (allowExisting)
{
target = targetContainer.OwnInventory.FindItemByIdentifier(targetPrefab.Identifier);
}
else
{
targetPrefab = null;
targetContainer = null;
return false;
}
return true;
}
public override void Update(float deltaTime)
{
base.Update(deltaTime);
if (target == null)
{
target = targetContainer.ContainedItems.FirstOrDefault(item => item.Prefab.Identifier == (containedPrefab != null ? itemContainerId : identifier) && !existingItems.Contains(item));
if (target != null)
{
if (containedPrefab != null)
{
for (int i = 0; i < spawnAmount; i++)
{
Entity.Spawner.AddItemToSpawnQueue(containedPrefab, target.OwnInventory);
}
}
existingItems.Clear();
}
}
}
public GoalFindItem(TraitorMission.CharacterFilter filter, string identifier, bool preferNew, bool allowNew, bool allowExisting, float percentage, params Identifier[] allowedContainerIdentifiers)
{
this.filter = filter;
this.identifier = identifier;
this.preferNew = preferNew;
this.allowNew = allowNew;
this.allowExisting = allowExisting;
this.percentage = percentage / 100f;
this.allowedContainerIdentifiers.UnionWith(allowedContainerIdentifiers);
}
}
}
}