(457e4ebe5) Fixed: Submarine navigation labels being translated when loading a sub in editor
This commit is contained in:
@@ -106,18 +106,6 @@ namespace Barotrauma
|
||||
subObjectives.Add(objective);
|
||||
}
|
||||
|
||||
public void RemoveSubObjective<T>(ref T objective) where T : AIObjective
|
||||
{
|
||||
if (objective != null)
|
||||
{
|
||||
if (subObjectives.Contains(objective))
|
||||
{
|
||||
subObjectives.Remove(objective);
|
||||
}
|
||||
objective = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void SortSubObjectives()
|
||||
{
|
||||
if (subObjectives.None()) { return; }
|
||||
|
||||
@@ -11,10 +11,9 @@ namespace Barotrauma
|
||||
class AIObjectiveCombat : AIObjective
|
||||
{
|
||||
public override string DebugTag => "combat";
|
||||
public bool useCoolDown = true;
|
||||
|
||||
private readonly CombatMode initialMode;
|
||||
|
||||
const float coolDown = 10.0f;
|
||||
const float CoolDown = 10.0f;
|
||||
|
||||
public Character Enemy { get; private set; }
|
||||
|
||||
@@ -26,7 +25,14 @@ namespace Barotrauma
|
||||
{
|
||||
_weapon = value;
|
||||
_weaponComponent = null;
|
||||
RemoveSubObjective(ref seekAmmunition);
|
||||
if (reloadWeaponObjective != null)
|
||||
{
|
||||
if (subObjectives.Contains(reloadWeaponObjective))
|
||||
{
|
||||
subObjectives.Remove(reloadWeaponObjective);
|
||||
}
|
||||
reloadWeaponObjective = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
private ItemComponent _weaponComponent;
|
||||
@@ -34,7 +40,6 @@ namespace Barotrauma
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Weapon == null) { return null; }
|
||||
if (_weaponComponent == null)
|
||||
{
|
||||
_weaponComponent =
|
||||
@@ -53,14 +58,12 @@ namespace Barotrauma
|
||||
private readonly HashSet<MeleeWeapon> meleeWeapons = new HashSet<MeleeWeapon>();
|
||||
private readonly HashSet<Item> adHocWeapons = new HashSet<Item>();
|
||||
|
||||
private AIObjectiveContainItem seekAmmunition;
|
||||
private AIObjectiveContainItem reloadWeaponObjective;
|
||||
private AIObjectiveGoTo retreatObjective;
|
||||
private AIObjectiveGoTo followTargetObjective;
|
||||
|
||||
private Hull retreatTarget;
|
||||
private float coolDownTimer;
|
||||
private IEnumerable<FarseerPhysics.Dynamics.Body> myBodies;
|
||||
private float aimTimer;
|
||||
|
||||
public enum CombatMode
|
||||
{
|
||||
@@ -75,7 +78,7 @@ namespace Barotrauma
|
||||
: base(character, objectiveManager, priorityModifier)
|
||||
{
|
||||
Enemy = enemy;
|
||||
coolDownTimer = coolDown;
|
||||
coolDownTimer = CoolDown;
|
||||
findSafety = objectiveManager.GetObjective<AIObjectiveFindSafety>();
|
||||
if (findSafety != null)
|
||||
{
|
||||
@@ -83,7 +86,6 @@ namespace Barotrauma
|
||||
findSafety.unreachable.Clear();
|
||||
}
|
||||
Mode = mode;
|
||||
initialMode = Mode;
|
||||
if (Enemy == null)
|
||||
{
|
||||
Mode = CombatMode.Retreat;
|
||||
@@ -102,7 +104,7 @@ namespace Barotrauma
|
||||
|
||||
public override bool IsCompleted()
|
||||
{
|
||||
bool completed = (Enemy != null && (Enemy.Removed || Enemy.IsDead)) || (initialMode != CombatMode.Offensive && coolDownTimer <= 0);
|
||||
bool completed = (Enemy != null && (Enemy.Removed || Enemy.IsDead)) || (useCoolDown && coolDownTimer <= 0);
|
||||
if (completed)
|
||||
{
|
||||
if (objectiveManager.CurrentOrder == this && Enemy != null && Enemy.IsDead)
|
||||
@@ -119,83 +121,39 @@ namespace Barotrauma
|
||||
|
||||
protected override void Act(float deltaTime)
|
||||
{
|
||||
if (initialMode != CombatMode.Offensive)
|
||||
if (useCoolDown)
|
||||
{
|
||||
coolDownTimer -= deltaTime;
|
||||
}
|
||||
if (abandon) { return; }
|
||||
TryArm();
|
||||
if (seekAmmunition == null || !subObjectives.Contains(seekAmmunition))
|
||||
{
|
||||
Move();
|
||||
if (Weapon != null)
|
||||
{
|
||||
OperateWeapon(deltaTime);
|
||||
}
|
||||
}
|
||||
Arm(deltaTime);
|
||||
Move(deltaTime);
|
||||
}
|
||||
|
||||
private void Move()
|
||||
private void Arm(float deltaTime)
|
||||
{
|
||||
switch (Mode)
|
||||
{
|
||||
case CombatMode.Offensive:
|
||||
Engage();
|
||||
break;
|
||||
case CombatMode.Defensive:
|
||||
case CombatMode.Retreat:
|
||||
Retreat();
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryArm()
|
||||
{
|
||||
if (Weapon != null)
|
||||
{
|
||||
if (!character.Inventory.Items.Contains(Weapon) || WeaponComponent == null)
|
||||
{
|
||||
Weapon = null;
|
||||
}
|
||||
else if (!WeaponComponent.HasRequiredContainedItems(false))
|
||||
{
|
||||
// Seek ammunition only if cannot find a new weapon
|
||||
if (!Reload(true, () => GetWeapon() == null))
|
||||
if (Weapon != null && !character.Inventory.Items.Contains(_weapon) || _weaponComponent != null && !_weaponComponent.HasRequiredContainedItems(false))
|
||||
{
|
||||
if (seekAmmunition != null && subObjectives.Contains(seekAmmunition))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Weapon = null;
|
||||
}
|
||||
Weapon = null;
|
||||
}
|
||||
if (Weapon == null)
|
||||
{
|
||||
Weapon = GetWeapon();
|
||||
}
|
||||
if (Weapon == null)
|
||||
{
|
||||
Mode = CombatMode.Retreat;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Weapon == null)
|
||||
{
|
||||
Weapon = GetWeapon();
|
||||
}
|
||||
if (Weapon == null)
|
||||
{
|
||||
Weapon = GetWeapon(ignoreRequiredItems: true);
|
||||
}
|
||||
Mode = Weapon == null ? CombatMode.Retreat : initialMode;
|
||||
return Weapon != null;
|
||||
}
|
||||
|
||||
private void OperateWeapon(float deltaTime)
|
||||
{
|
||||
switch (Mode)
|
||||
{
|
||||
case CombatMode.Offensive:
|
||||
case CombatMode.Defensive:
|
||||
if (Equip())
|
||||
{
|
||||
Attack(deltaTime);
|
||||
if (Reload(deltaTime))
|
||||
{
|
||||
Attack(deltaTime);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CombatMode.Retreat:
|
||||
@@ -205,7 +163,23 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private Item GetWeapon(bool ignoreRequiredItems = false)
|
||||
private void Move(float deltaTime)
|
||||
{
|
||||
switch (Mode)
|
||||
{
|
||||
case CombatMode.Offensive:
|
||||
Engage(deltaTime);
|
||||
break;
|
||||
case CombatMode.Defensive:
|
||||
case CombatMode.Retreat:
|
||||
Retreat(deltaTime);
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
private Item GetWeapon()
|
||||
{
|
||||
rangedWeapons.Clear();
|
||||
meleeWeapons.Clear();
|
||||
@@ -219,14 +193,14 @@ namespace Barotrauma
|
||||
{
|
||||
if (component is RangedWeapon rw)
|
||||
{
|
||||
if (ignoreRequiredItems || rw.HasRequiredContainedItems(false))
|
||||
if (rw.HasRequiredContainedItems(false))
|
||||
{
|
||||
rangedWeapons.Add(rw);
|
||||
}
|
||||
}
|
||||
else if (component is MeleeWeapon mw)
|
||||
{
|
||||
if (ignoreRequiredItems || mw.HasRequiredContainedItems(false))
|
||||
if (mw.HasRequiredContainedItems(false))
|
||||
{
|
||||
meleeWeapons.Add(mw);
|
||||
}
|
||||
@@ -242,7 +216,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (statusEffect.Afflictions.Any())
|
||||
{
|
||||
if (ignoreRequiredItems || component.HasRequiredContainedItems(false))
|
||||
if (component.HasRequiredContainedItems(false))
|
||||
{
|
||||
adHocWeapons.Add(item);
|
||||
}
|
||||
@@ -279,29 +253,19 @@ namespace Barotrauma
|
||||
Weapon.Drop(character);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool Equip()
|
||||
{
|
||||
if (!WeaponComponent.HasRequiredContainedItems(false))
|
||||
if (!character.SelectedItems.Contains(Weapon))
|
||||
{
|
||||
Mode = CombatMode.Retreat;
|
||||
return false;
|
||||
}
|
||||
//if (!character.SelectedItems.Contains(Weapon))
|
||||
if (!character.HasEquippedItem(Weapon))
|
||||
{
|
||||
Weapon.TryInteract(character, forceSelectKey: true);
|
||||
var slots = Weapon.AllowedSlots.FindAll(s => s == InvSlotType.LeftHand || s == InvSlotType.RightHand || s == (InvSlotType.LeftHand | InvSlotType.RightHand));
|
||||
if (character.Inventory.TryPutItem(Weapon, character, slots))
|
||||
{
|
||||
Weapon.Equip(character);
|
||||
aimTimer = Rand.Range(0.5f, 1f);
|
||||
}
|
||||
else
|
||||
{
|
||||
Weapon = null;
|
||||
Mode = CombatMode.Retreat;
|
||||
return false;
|
||||
}
|
||||
@@ -309,10 +273,16 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
|
||||
private void Retreat()
|
||||
private void Retreat(float deltaTime)
|
||||
{
|
||||
RemoveSubObjective(ref followTargetObjective);
|
||||
RemoveSubObjective(ref seekAmmunition);
|
||||
if (followTargetObjective != null)
|
||||
{
|
||||
if (subObjectives.Contains(followTargetObjective))
|
||||
{
|
||||
subObjectives.Remove(followTargetObjective);
|
||||
}
|
||||
followTargetObjective = null;
|
||||
}
|
||||
if (retreatObjective != null && retreatObjective.Target != retreatTarget)
|
||||
{
|
||||
retreatObjective = null;
|
||||
@@ -324,115 +294,59 @@ namespace Barotrauma
|
||||
TryAddSubObjective(ref retreatObjective, () => new AIObjectiveGoTo(retreatTarget, character, objectiveManager, false, true));
|
||||
}
|
||||
|
||||
private void Engage()
|
||||
private void Engage(float deltaTime)
|
||||
{
|
||||
retreatTarget = null;
|
||||
RemoveSubObjective(ref retreatObjective);
|
||||
RemoveSubObjective(ref seekAmmunition);
|
||||
if (followTargetObjective != null && followTargetObjective.Target != Enemy)
|
||||
if (retreatObjective != null)
|
||||
{
|
||||
followTargetObjective = null;
|
||||
if (subObjectives.Contains(retreatObjective))
|
||||
{
|
||||
subObjectives.Remove(retreatObjective);
|
||||
}
|
||||
retreatObjective = null;
|
||||
}
|
||||
TryAddSubObjective(ref followTargetObjective,
|
||||
constructor: () => new AIObjectiveGoTo(Enemy, character, objectiveManager, repeat: true, getDivingGearIfNeeded: true)
|
||||
{
|
||||
AllowGoingOutside = true,
|
||||
IgnoreIfTargetDead = true,
|
||||
CheckVisibility = true
|
||||
CheckVisibility = true,
|
||||
CloseEnough =
|
||||
WeaponComponent is RangedWeapon ? 3 :
|
||||
WeaponComponent is MeleeWeapon mw ? ConvertUnits.ToSimUnits(mw.Range) :
|
||||
WeaponComponent is RepairTool rt ? ConvertUnits.ToSimUnits(rt.Range) : 0.5f
|
||||
},
|
||||
onAbandon: () =>
|
||||
{
|
||||
Mode = CombatMode.Retreat;
|
||||
SteeringManager.Reset();
|
||||
Mode = CombatMode.Retreat;
|
||||
});
|
||||
if (followTargetObjective != null && subObjectives.Contains(followTargetObjective))
|
||||
{
|
||||
followTargetObjective.CloseEnough =
|
||||
WeaponComponent is RangedWeapon ? 3 :
|
||||
WeaponComponent is MeleeWeapon mw ? ConvertUnits.ToSimUnits(mw.Range) :
|
||||
WeaponComponent is RepairTool rt ? ConvertUnits.ToSimUnits(rt.Range) : 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeks for more ammunition. Creates a new subobjective.
|
||||
/// </summary>
|
||||
private void SeekAmmunition(string[] ammunitionIdentifiers)
|
||||
private bool Reload(float deltaTime)
|
||||
{
|
||||
retreatTarget = null;
|
||||
RemoveSubObjective(ref retreatObjective);
|
||||
RemoveSubObjective(ref followTargetObjective);
|
||||
TryAddSubObjective(ref seekAmmunition,
|
||||
constructor: () => new AIObjectiveContainItem(character, ammunitionIdentifiers, Weapon.GetComponent<ItemContainer>(), objectiveManager)
|
||||
{
|
||||
targetItemCount = Weapon.GetComponent<ItemContainer>().Capacity,
|
||||
checkInventory = false
|
||||
},
|
||||
onAbandon: () =>
|
||||
{
|
||||
Weapon = null;
|
||||
Mode = CombatMode.Retreat;
|
||||
SteeringManager.Reset();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reloads the ammunition found in the inventory.
|
||||
/// If seekAmmo is true and the condition is met or not provided, tries to get find the ammo elsewhere.
|
||||
/// </summary>
|
||||
private bool Reload(bool seekAmmo, Func<bool> condition = null)
|
||||
{
|
||||
if (WeaponComponent == null) { return false; }
|
||||
if (!WeaponComponent.requiredItems.ContainsKey(RelatedItem.RelationType.Contained)) { return false; }
|
||||
var containedItems = Weapon.ContainedItems;
|
||||
RelatedItem item = null;
|
||||
Item ammunition = null;
|
||||
string[] ammunitionIdentifiers = null;
|
||||
foreach (RelatedItem requiredItem in WeaponComponent.requiredItems[RelatedItem.RelationType.Contained])
|
||||
if (WeaponComponent != null && WeaponComponent.requiredItems.ContainsKey(RelatedItem.RelationType.Contained))
|
||||
{
|
||||
ammunition = containedItems.FirstOrDefault(it => it.Condition > 0.0f && requiredItem.MatchesItem(it));
|
||||
if (ammunition != null)
|
||||
var containedItems = Weapon.ContainedItems;
|
||||
foreach (RelatedItem requiredItem in WeaponComponent.requiredItems[RelatedItem.RelationType.Contained])
|
||||
{
|
||||
// Ammunition still remaining
|
||||
return true;
|
||||
}
|
||||
item = requiredItem;
|
||||
ammunitionIdentifiers = requiredItem.Identifiers;
|
||||
}
|
||||
// No ammo
|
||||
if (ammunition == null)
|
||||
{
|
||||
var container = Weapon.GetComponent<ItemContainer>();
|
||||
// Try reload ammunition in inventory
|
||||
foreach (string identifier in ammunitionIdentifiers)
|
||||
{
|
||||
foreach (var i in character.Inventory.Items)
|
||||
Item containedItem = containedItems.FirstOrDefault(it => it.Condition > 0.0f && requiredItem.MatchesItem(it));
|
||||
if (containedItem == null)
|
||||
{
|
||||
if (i == null) { continue; }
|
||||
if (i.Prefab.Identifier == identifier || i.HasTag(identifier))
|
||||
{
|
||||
if (i.Condition > 0)
|
||||
TryAddSubObjective(ref reloadWeaponObjective,
|
||||
constructor: () => new AIObjectiveContainItem(character, requiredItem.Identifiers, Weapon.GetComponent<ItemContainer>(), objectiveManager),
|
||||
onAbandon: () =>
|
||||
{
|
||||
container.Inventory.TryPutItem(ammunition, null);
|
||||
}
|
||||
}
|
||||
SteeringManager.Reset();
|
||||
Mode = CombatMode.Retreat;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (WeaponComponent.HasRequiredContainedItems(false))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (ammunition == null)
|
||||
{
|
||||
if (seekAmmo && ammunitionIdentifiers != null && (condition == null || condition()))
|
||||
{
|
||||
SeekAmmunition(ammunitionIdentifiers);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return reloadWeaponObjective == null || reloadWeaponObjective.IsCompleted();
|
||||
}
|
||||
|
||||
private IEnumerable<FarseerPhysics.Dynamics.Body> myBodies;
|
||||
private void Attack(float deltaTime)
|
||||
{
|
||||
float squaredDistance = Vector2.DistanceSquared(character.Position, Enemy.Position);
|
||||
@@ -457,16 +371,6 @@ namespace Barotrauma
|
||||
character.SetInput(InputType.Aim, false, true);
|
||||
}
|
||||
}
|
||||
bool isFacing = character.AnimController.Dir > 0 && Enemy.WorldPosition.X > character.WorldPosition.X || character.AnimController.Dir < 0 && Enemy.WorldPosition.X < character.WorldPosition.X;
|
||||
if (!isFacing)
|
||||
{
|
||||
aimTimer = Rand.Range(1f, 1.5f);
|
||||
}
|
||||
if (aimTimer > 0)
|
||||
{
|
||||
aimTimer -= deltaTime;
|
||||
return;
|
||||
}
|
||||
if (WeaponComponent is MeleeWeapon meleeWeapon)
|
||||
{
|
||||
if (squaredDistance <= meleeWeapon.Range * meleeWeapon.Range)
|
||||
@@ -481,14 +385,14 @@ namespace Barotrauma
|
||||
{
|
||||
if (squaredDistance > repairTool.Range * repairTool.Range) { return; }
|
||||
}
|
||||
if (VectorExtensions.Angle(VectorExtensions.Forward(Weapon.body.TransformedRotation), Enemy.Position - Weapon.Position) < MathHelper.PiOver4)
|
||||
if (VectorExtensions.Angle(VectorExtensions.Forward(Weapon.body.TransformedRotation), Enemy.Position - character.Position) < MathHelper.PiOver4)
|
||||
{
|
||||
if (myBodies == null)
|
||||
{
|
||||
myBodies = character.AnimController.Limbs.Select(l => l.body.FarseerBody);
|
||||
}
|
||||
var collisionCategories = Physics.CollisionCharacter | Physics.CollisionWall;
|
||||
var pickedBody = Submarine.PickBody(Weapon.SimPosition, Enemy.SimPosition, myBodies, collisionCategories);
|
||||
var pickedBody = Submarine.PickBody(character.SimPosition, Enemy.SimPosition, myBodies, collisionCategories);
|
||||
if (pickedBody != null)
|
||||
{
|
||||
Character target = null;
|
||||
@@ -500,11 +404,10 @@ namespace Barotrauma
|
||||
{
|
||||
target = limb.character;
|
||||
}
|
||||
if (target != null && (target == Enemy || !HumanAIController.IsFriendly(target)))
|
||||
if (target != null && target == Enemy)
|
||||
{
|
||||
character.SetInput(InputType.Shoot, false, true);
|
||||
Weapon.Use(deltaTime, character);
|
||||
aimTimer = Rand.Range(0.25f, 0.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+16
-12
@@ -11,13 +11,12 @@ namespace Barotrauma
|
||||
|
||||
public Func<Item, float> GetItemPriority;
|
||||
|
||||
public int targetItemCount = 1;
|
||||
public int MinContainedAmount = 1;
|
||||
public string[] ignoredContainerIdentifiers;
|
||||
public bool checkInventory = true;
|
||||
|
||||
//can either be a tag or an identifier
|
||||
public readonly string[] itemIdentifiers;
|
||||
public readonly ItemContainer container;
|
||||
private readonly string[] itemIdentifiers;
|
||||
private readonly ItemContainer container;
|
||||
|
||||
private bool isCompleted;
|
||||
private AIObjectiveGetItem getItemObjective;
|
||||
@@ -40,6 +39,7 @@ namespace Barotrauma
|
||||
|
||||
public override bool IsCompleted()
|
||||
{
|
||||
if (isCompleted) { return true; }
|
||||
int containedItemCount = 0;
|
||||
foreach (Item item in container.Inventory.Items)
|
||||
{
|
||||
@@ -48,7 +48,7 @@ namespace Barotrauma
|
||||
containedItemCount++;
|
||||
}
|
||||
}
|
||||
return containedItemCount >= targetItemCount;
|
||||
return containedItemCount >= MinContainedAmount;
|
||||
}
|
||||
|
||||
public override float GetPriority()
|
||||
@@ -62,6 +62,7 @@ namespace Barotrauma
|
||||
|
||||
protected override void Act(float deltaTime)
|
||||
{
|
||||
if (isCompleted) { return; }
|
||||
//get the item that should be contained
|
||||
Item itemToContain = null;
|
||||
foreach (string identifier in itemIdentifiers)
|
||||
@@ -71,13 +72,8 @@ namespace Barotrauma
|
||||
}
|
||||
if (itemToContain == null)
|
||||
{
|
||||
if (getItemObjective != null && getItemObjective.IsCompleted())
|
||||
{
|
||||
getItemObjective = null;
|
||||
targetItemCount--;
|
||||
}
|
||||
TryAddSubObjective(ref getItemObjective, () =>
|
||||
new AIObjectiveGetItem(character, itemIdentifiers, objectiveManager, checkInventory: checkInventory)
|
||||
new AIObjectiveGetItem(character, itemIdentifiers, objectiveManager)
|
||||
{
|
||||
GetItemPriority = GetItemPriority,
|
||||
ignoredContainerIdentifiers = ignoredContainerIdentifiers
|
||||
@@ -85,7 +81,14 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
if (container.Item.ParentInventory == character.Inventory)
|
||||
{
|
||||
{
|
||||
var containedItems = container.Inventory.Items;
|
||||
//if there's already something in the mask (empty oxygen tank?), drop it
|
||||
var existingItem = containedItems.FirstOrDefault(i => i != null);
|
||||
if (existingItem != null)
|
||||
{
|
||||
existingItem.Drop(character);
|
||||
}
|
||||
character.Inventory.RemoveItem(itemToContain);
|
||||
container.Inventory.TryPutItem(itemToContain, null);
|
||||
}
|
||||
@@ -99,6 +102,7 @@ namespace Barotrauma
|
||||
}
|
||||
container.Combine(itemToContain);
|
||||
}
|
||||
isCompleted = true;
|
||||
}
|
||||
|
||||
public override bool IsDuplicate(AIObjective otherObjective)
|
||||
|
||||
+1
-2
@@ -10,7 +10,6 @@ namespace Barotrauma
|
||||
class AIObjectiveFightIntruders : AIObjectiveLoop<Character>
|
||||
{
|
||||
public override string DebugTag => "fight intruders";
|
||||
protected override float IgnoreListClearInterval => 30;
|
||||
|
||||
public AIObjectiveFightIntruders(Character character, AIObjectiveManager objectiveManager, float priorityModifier = 1)
|
||||
: base(character, objectiveManager, priorityModifier) { }
|
||||
@@ -30,7 +29,7 @@ namespace Barotrauma
|
||||
|
||||
protected override IEnumerable<Character> GetList() => Character.CharacterList;
|
||||
|
||||
protected override AIObjective ObjectiveConstructor(Character target) => new AIObjectiveCombat(character, target, AIObjectiveCombat.CombatMode.Offensive, objectiveManager, PriorityModifier);
|
||||
protected override AIObjective ObjectiveConstructor(Character target) => new AIObjectiveCombat(character, target, AIObjectiveCombat.CombatMode.Offensive, objectiveManager, PriorityModifier) { useCoolDown = false };
|
||||
|
||||
protected override float TargetEvaluation()
|
||||
{
|
||||
|
||||
@@ -275,6 +275,31 @@ namespace Barotrauma
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("AIObjectiveFixLeak failed - the item \"" + weldingTool + "\" has no RepairTool component but is tagged as a welding tool");
|
||||
#endif
|
||||
abandon = true;
|
||||
return;
|
||||
}
|
||||
Vector2 gapDiff = Leak.WorldPosition - character.WorldPosition;
|
||||
// TODO: use the collider size/reach?
|
||||
if (!character.AnimController.InWater && Math.Abs(gapDiff.X) < 100 && gapDiff.Y < 0.0f && gapDiff.Y > -150)
|
||||
{
|
||||
HumanAIController.AnimController.Crouching = true;
|
||||
}
|
||||
float reach = ConvertUnits.ToSimUnits(repairTool.Range);
|
||||
bool canOperate = ConvertUnits.ToSimUnits(gapDiff.Length()) < reach;
|
||||
if (canOperate)
|
||||
{
|
||||
TryAddSubObjective(ref operateObjective, () => new AIObjectiveOperateItem(repairTool, character, objectiveManager, option: "", requireEquip: true, operateTarget: Leak));
|
||||
}
|
||||
else
|
||||
{
|
||||
TryAddSubObjective(ref gotoObjective, () => new AIObjectiveGoTo(ConvertUnits.ToSimUnits(GetStandPosition()), character, objectiveManager) { CloseEnough = reach * 0.75f });
|
||||
}
|
||||
var repairTool = weldingTool.GetComponent<RepairTool>();
|
||||
if (repairTool == null)
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("AIObjectiveFixLeak failed - the item \"" + weldingTool + "\" has no RepairTool component but is tagged as a welding tool");
|
||||
#endif
|
||||
abandon = true;
|
||||
return;
|
||||
|
||||
@@ -41,10 +41,10 @@ namespace Barotrauma
|
||||
this.targetItem = targetItem;
|
||||
}
|
||||
|
||||
public AIObjectiveGetItem(Character character, string itemIdentifier, AIObjectiveManager objectiveManager, bool equip = false, bool checkInventory = true, float priorityModifier = 1)
|
||||
: this(character, new string[] { itemIdentifier }, objectiveManager, equip, checkInventory, priorityModifier) { }
|
||||
public AIObjectiveGetItem(Character character, string itemIdentifier, AIObjectiveManager objectiveManager, bool equip = false, float priorityModifier = 1)
|
||||
: this(character, new string[] { itemIdentifier }, objectiveManager, equip, priorityModifier) { }
|
||||
|
||||
public AIObjectiveGetItem(Character character, string[] itemIdentifiers, AIObjectiveManager objectiveManager, bool equip = false, bool checkInventory = true, float priorityModifier = 1)
|
||||
public AIObjectiveGetItem(Character character, string[] itemIdentifiers, AIObjectiveManager objectiveManager, bool equip = false, float priorityModifier = 1)
|
||||
: base(character, objectiveManager, priorityModifier)
|
||||
{
|
||||
currSearchIndex = -1;
|
||||
@@ -54,10 +54,7 @@ namespace Barotrauma
|
||||
{
|
||||
itemIdentifiers[i] = itemIdentifiers[i].ToLowerInvariant();
|
||||
}
|
||||
if (checkInventory)
|
||||
{
|
||||
CheckInventory();
|
||||
}
|
||||
CheckInventory();
|
||||
}
|
||||
|
||||
private void CheckInventory()
|
||||
@@ -228,7 +225,8 @@ namespace Barotrauma
|
||||
|
||||
public override bool IsDuplicate(AIObjective otherObjective)
|
||||
{
|
||||
if (!(otherObjective is AIObjectiveGetItem getItem)) { return false; }
|
||||
AIObjectiveGetItem getItem = otherObjective as AIObjectiveGetItem;
|
||||
if (getItem == null) { return false; }
|
||||
if (getItem.equip != equip) { return false; }
|
||||
if (getItem.itemIdentifiers != null && itemIdentifiers != null)
|
||||
{
|
||||
@@ -248,11 +246,7 @@ namespace Barotrauma
|
||||
|
||||
public override bool IsCompleted()
|
||||
{
|
||||
if (targetItem != null)
|
||||
{
|
||||
return HasItem(targetItem);
|
||||
}
|
||||
else if (itemIdentifiers != null)
|
||||
if (itemIdentifiers != null)
|
||||
{
|
||||
foreach (string itemName in itemIdentifiers)
|
||||
{
|
||||
@@ -264,6 +258,10 @@ namespace Barotrauma
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (targetItem != null)
|
||||
{
|
||||
return character.Inventory.Items.Contains(targetItem) && (!equip || character.HasEquippedItem(targetItem));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -73,6 +73,21 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
if (objectiveManager.CurrentObjective == this)
|
||||
{
|
||||
if (randomTimer > 0)
|
||||
{
|
||||
randomTimer -= deltaTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetRandom();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsCompleted() => false;
|
||||
public override bool CanBeCompleted => true;
|
||||
|
||||
|
||||
@@ -282,6 +282,10 @@ namespace Barotrauma
|
||||
{
|
||||
isCompleted = true;
|
||||
}
|
||||
if (component.AIOperate(deltaTime, character, this))
|
||||
{
|
||||
isCompleted = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+1
-39
@@ -4,7 +4,6 @@ using System;
|
||||
using System.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using FarseerPhysics;
|
||||
using Barotrauma.Items.Components;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -15,7 +14,6 @@ namespace Barotrauma
|
||||
public Item Item { get; private set; }
|
||||
|
||||
private AIObjectiveGoTo goToObjective;
|
||||
private AIObjectiveContainItem refuelObjective;
|
||||
private float previousCondition = -1;
|
||||
private RepairTool repairTool;
|
||||
|
||||
@@ -73,46 +71,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
// Only continue when the get item sub objectives have been completed.
|
||||
if (subObjectives.Any()) { return; }
|
||||
if (subObjectives.Any(so => so is AIObjectiveGetItem)) { return; }
|
||||
if (repairTool == null)
|
||||
{
|
||||
FindRepairTool();
|
||||
}
|
||||
if (repairTool != null)
|
||||
{
|
||||
var containedItems = repairTool.Item.ContainedItems;
|
||||
if (containedItems == null)
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("AIObjectiveRepairItem failed - the item \"" + repairTool + "\" has no proper inventory");
|
||||
#endif
|
||||
abandon = true;
|
||||
return;
|
||||
}
|
||||
// Drop empty tanks
|
||||
foreach (Item containedItem in containedItems)
|
||||
{
|
||||
if (containedItem == null) { continue; }
|
||||
if (containedItem.Condition <= 0.0f)
|
||||
{
|
||||
containedItem.Drop(character);
|
||||
}
|
||||
}
|
||||
RelatedItem item = null;
|
||||
Item fuel = null;
|
||||
foreach (RelatedItem requiredItem in repairTool.requiredItems[RelatedItem.RelationType.Contained])
|
||||
{
|
||||
item = requiredItem;
|
||||
fuel = containedItems.FirstOrDefault(it => it.Condition > 0.0f && requiredItem.MatchesItem(it));
|
||||
if (fuel != null) { break; }
|
||||
}
|
||||
if (fuel == null)
|
||||
{
|
||||
RemoveSubObjective(ref goToObjective);
|
||||
TryAddSubObjective(ref refuelObjective, () => new AIObjectiveContainItem(character, item.Identifiers, repairTool.Item.GetComponent<ItemContainer>(), objectiveManager));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (character.CurrentHull == Item.CurrentHull && character.CanInteractWith(Item))
|
||||
{
|
||||
if (repairTool != null)
|
||||
@@ -149,7 +112,6 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveSubObjective(ref refuelObjective);
|
||||
// If cannot reach the item, approach it.
|
||||
TryAddSubObjective(ref goToObjective,
|
||||
constructor: () =>
|
||||
|
||||
@@ -203,9 +203,7 @@ namespace Barotrauma
|
||||
|
||||
if (startNode == null)
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.NewMessage("Pathfinding error, couldn't find a start node. "+ errorMsgStr, Color.DarkRed);
|
||||
#endif
|
||||
|
||||
return new SteeringPath(true);
|
||||
}
|
||||
@@ -255,9 +253,7 @@ namespace Barotrauma
|
||||
|
||||
if (endNode == null)
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.NewMessage("Pathfinding error, couldn't find an end node. " + errorMsgStr, Color.DarkRed);
|
||||
#endif
|
||||
return new SteeringPath(true);
|
||||
}
|
||||
|
||||
@@ -285,9 +281,7 @@ namespace Barotrauma
|
||||
|
||||
if (startNode == null || endNode == null)
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.NewMessage("Pathfinding error, couldn't find matching pathnodes to waypoints.", Color.DarkRed);
|
||||
#endif
|
||||
return new SteeringPath(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -132,11 +132,13 @@ namespace Barotrauma
|
||||
#else
|
||||
if (!CrewManager.GetCharacters().Contains(character)) { continue; }
|
||||
#endif
|
||||
if (character.Submarine == Level.Loaded.StartOutpost && character.CurrentHull == startWatchman.CurrentHull)
|
||||
if (character.Submarine == Level.Loaded.StartOutpost &&
|
||||
Vector2.DistanceSquared(character.WorldPosition, startWatchman.WorldPosition) < 500.0f * 500.0f)
|
||||
{
|
||||
CreateDialog(new List<Character> { startWatchman }, "EnterStartOutpost", 5 * 60.0f);
|
||||
}
|
||||
else if (character.Submarine == Level.Loaded.EndOutpost && character.CurrentHull == endWatchman.CurrentHull)
|
||||
else if (character.Submarine == Level.Loaded.EndOutpost &&
|
||||
Vector2.DistanceSquared(character.WorldPosition, endWatchman.WorldPosition) < 500.0f * 500.0f)
|
||||
{
|
||||
CreateDialog(new List<Character> { endWatchman }, "EnterEndOutpost", 5 * 60.0f);
|
||||
}
|
||||
|
||||
@@ -905,6 +905,25 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
if (targetItem.Prefab.DeconstructItems.Any())
|
||||
{
|
||||
inputContainer.Inventory.RemoveItem(targetItem);
|
||||
Entity.Spawner.AddToRemoveQueue(targetItem);
|
||||
MoveInputQueue();
|
||||
PutItemsToLinkedContainer();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (outputContainer.Inventory.Items.All(i => i != null))
|
||||
{
|
||||
targetItem.Drop(dropper: null);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputContainer.Inventory.TryPutItem(targetItem, user: null, createNetworkEvent: true);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetItem.Prefab.DeconstructItems.Any())
|
||||
{
|
||||
inputContainer.Inventory.RemoveItem(targetItem);
|
||||
|
||||
@@ -501,7 +501,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
var containFuelObjective = new AIObjectiveContainItem(character, new string[] { "fuelrod", "reactorfuel" }, item.GetComponent<ItemContainer>(), objective.objectiveManager)
|
||||
{
|
||||
targetItemCount = item.ContainedItems.Count(i => i != null && i.Prefab.Identifier == "fuelrod" || i.HasTag("reactorfuel")) + 1,
|
||||
MinContainedAmount = item.ContainedItems.Count(i => i != null && i.Prefab.Identifier == "fuelrod" || i.HasTag("reactorfuel")) + 1,
|
||||
GetItemPriority = (Item fuelItem) =>
|
||||
{
|
||||
if (fuelItem.ParentInventory?.Owner is Item)
|
||||
|
||||
@@ -212,33 +212,6 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2? PosToMaintain
|
||||
{
|
||||
get { return posToMaintain; }
|
||||
set { posToMaintain = value; }
|
||||
}
|
||||
|
||||
struct ObstacleDebugInfo
|
||||
{
|
||||
public Vector2 Point1;
|
||||
public Vector2 Point2;
|
||||
|
||||
public Vector2? Intersection;
|
||||
|
||||
public float Dot;
|
||||
|
||||
public Vector2 AvoidStrength;
|
||||
|
||||
public ObstacleDebugInfo(GraphEdge edge, Vector2? intersection, float dot, Vector2 avoidStrength)
|
||||
{
|
||||
Point1 = edge.Point1;
|
||||
Point2 = edge.Point2;
|
||||
Intersection = intersection;
|
||||
Dot = dot;
|
||||
AvoidStrength = avoidStrength;
|
||||
}
|
||||
}
|
||||
|
||||
//edge point 1, edge point 2, avoid strength
|
||||
private List<ObstacleDebugInfo> debugDrawObstacles = new List<ObstacleDebugInfo>();
|
||||
|
||||
|
||||
@@ -125,7 +125,14 @@ namespace Barotrauma.Items.Components
|
||||
for (int i = 0; i < labels.Length; i++)
|
||||
{
|
||||
labels[i] = i < newLabels.Length ? newLabels[i] : customInterfaceElementList[i].Label;
|
||||
customInterfaceElementList[i].Label = TextManager.Get(labels[i], returnNull: true) ?? labels[i];
|
||||
if (Screen.Selected != GameMain.SubEditorScreen)
|
||||
{
|
||||
customInterfaceElementList[i].Label = TextManager.Get(labels[i], returnNull: true) ?? labels[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
customInterfaceElementList[i].Label = labels[i];
|
||||
}
|
||||
}
|
||||
UpdateLabelsProjSpecific();
|
||||
}
|
||||
|
||||
@@ -460,7 +460,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
var containShellObjective = new AIObjectiveContainItem(character, container.ContainableItems[0].Identifiers[0], container, objective.objectiveManager);
|
||||
character?.Speak(TextManager.Get("DialogLoadTurret").Replace("[itemname]", item.Name), null, 0.0f, "loadturret", 30.0f);
|
||||
containShellObjective.targetItemCount = usableProjectileCount + 1;
|
||||
containShellObjective.MinContainedAmount = usableProjectileCount + 1;
|
||||
containShellObjective.ignoredContainerIdentifiers = new string[] { containerItem.prefab.Identifier };
|
||||
objective.AddSubObjective(containShellObjective);
|
||||
return false;
|
||||
|
||||
@@ -1172,6 +1172,38 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateTransform()
|
||||
{
|
||||
Submarine prevSub = Submarine;
|
||||
|
||||
FindHull();
|
||||
|
||||
if (Submarine == null && prevSub != null)
|
||||
{
|
||||
body.SetTransform(body.SimPosition + prevSub.SimPosition, body.Rotation);
|
||||
}
|
||||
else if (Submarine != null && prevSub == null)
|
||||
{
|
||||
body.SetTransform(body.SimPosition - Submarine.SimPosition, body.Rotation);
|
||||
}
|
||||
else if (Submarine != null && prevSub != null && Submarine != prevSub)
|
||||
{
|
||||
body.SetTransform(body.SimPosition + prevSub.SimPosition - Submarine.SimPosition, body.Rotation);
|
||||
}
|
||||
|
||||
Vector2 displayPos = ConvertUnits.ToDisplayUnits(body.SimPosition);
|
||||
rect.X = (int)(displayPos.X - rect.Width / 2.0f);
|
||||
rect.Y = (int)(displayPos.Y + rect.Height / 2.0f);
|
||||
|
||||
if (Math.Abs(body.LinearVelocity.X) > NetConfig.MaxPhysicsBodyVelocity ||
|
||||
Math.Abs(body.LinearVelocity.Y) > NetConfig.MaxPhysicsBodyVelocity)
|
||||
{
|
||||
body.LinearVelocity = new Vector2(
|
||||
MathHelper.Clamp(body.LinearVelocity.X, -NetConfig.MaxPhysicsBodyVelocity, NetConfig.MaxPhysicsBodyVelocity),
|
||||
MathHelper.Clamp(body.LinearVelocity.Y, -NetConfig.MaxPhysicsBodyVelocity, NetConfig.MaxPhysicsBodyVelocity));
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateTransform()
|
||||
{
|
||||
Submarine prevSub = Submarine;
|
||||
|
||||
@@ -443,12 +443,22 @@ namespace Barotrauma
|
||||
|
||||
identifier = element.GetAttributeString("identifier", "");
|
||||
|
||||
name = TextManager.Get("EntityName." + identifier, true) ?? element.GetAttributeString("name", "");
|
||||
if (name == "") DebugConsole.ThrowError("Unnamed item in " + filePath + "!");
|
||||
|
||||
//nameidentifier can be used to make multiple items use the same names and descriptions
|
||||
string nameIdentifier = element.GetAttributeString("nameidentifier", "");
|
||||
|
||||
if (string.IsNullOrEmpty(nameIdentifier))
|
||||
{
|
||||
name = TextManager.Get("EntityName." + identifier, true) ?? element.GetAttributeString("name", "");
|
||||
}
|
||||
else
|
||||
{
|
||||
name = TextManager.Get("EntityName." + nameIdentifier, true) ?? element.GetAttributeString("name", "");
|
||||
}
|
||||
|
||||
if (name == "") { DebugConsole.ThrowError("Unnamed item in " + filePath + "!"); }
|
||||
|
||||
DebugConsole.Log(" " + name);
|
||||
|
||||
Aliases = element.GetAttributeStringArray("aliases", new string[0], convertToLowerInvariant: true);
|
||||
|
||||
if (!Enum.TryParse(element.GetAttributeString("category", "Misc"), true, out MapEntityCategory category))
|
||||
@@ -481,7 +491,15 @@ namespace Barotrauma
|
||||
|
||||
SerializableProperty.DeserializeProperties(this, element);
|
||||
|
||||
string translatedDescription = TextManager.Get("EntityDescription." + identifier, true);
|
||||
string translatedDescription = "";
|
||||
if (string.IsNullOrEmpty(nameIdentifier))
|
||||
{
|
||||
translatedDescription = TextManager.Get("EntityDescription." + identifier, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
translatedDescription = TextManager.Get("EntityDescription." + nameIdentifier, true);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(translatedDescription)) Description = translatedDescription;
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
|
||||
@@ -246,6 +246,25 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public string DisplayName
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
private string roomName;
|
||||
[Editable, Serialize("", true, translationTextTag: "RoomName.")]
|
||||
public string RoomName
|
||||
{
|
||||
get { return roomName; }
|
||||
set
|
||||
{
|
||||
if (roomName == value) { return; }
|
||||
roomName = value;
|
||||
DisplayName = TextManager.Get(roomName, returnNull: true) ?? roomName;
|
||||
}
|
||||
}
|
||||
|
||||
public override Rectangle Rect
|
||||
{
|
||||
get
|
||||
|
||||
@@ -1364,7 +1364,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (Hull hull in matchingHulls)
|
||||
{
|
||||
if (string.IsNullOrEmpty(hull.RoomName))
|
||||
if (string.IsNullOrEmpty(hull.RoomName) || !hull.RoomName.Contains("RoomName."))
|
||||
{
|
||||
hull.RoomName = hull.CreateRoomName();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user