Build 0.20.0.0
This commit is contained in:
@@ -442,6 +442,7 @@ namespace Barotrauma
|
||||
base.Update(deltaTime);
|
||||
UpdateTriggers(deltaTime);
|
||||
Character.ClearInputs();
|
||||
Reverse = false;
|
||||
|
||||
bool ignorePlatforms = Character.AnimController.TargetMovement.Y < -0.5f && (-Character.AnimController.TargetMovement.Y > Math.Abs(Character.AnimController.TargetMovement.X));
|
||||
if (steeringManager == insideSteering)
|
||||
@@ -804,10 +805,6 @@ namespace Barotrauma
|
||||
Reverse = true;
|
||||
run = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Reverse = false;
|
||||
}
|
||||
SteeringManager.SteeringManual(deltaTime, dir * 0.2f);
|
||||
}
|
||||
else
|
||||
@@ -1490,40 +1487,26 @@ namespace Barotrauma
|
||||
canAttack = angle < MathHelper.ToRadians(AttackLimb.attack.RequiredAngle);
|
||||
if (canAttack && AttackLimb.attack.AvoidFriendlyFire)
|
||||
{
|
||||
float minDistance = MathUtils.Pow(ConvertUnits.ToDisplayUnits(Character.AnimController.Collider.GetMaxExtent() * 3), 2);
|
||||
bool IsFarEnough(Character other) => Vector2.DistanceSquared(Character.WorldPosition, other.WorldPosition) > minDistance;
|
||||
if (SwarmBehavior != null)
|
||||
canAttack = !IsBlocked(Character.GetRelativeSimPosition(SelectedAiTarget.Entity));
|
||||
bool IsBlocked(Vector2 targetPosition)
|
||||
{
|
||||
canAttack = SwarmBehavior.Members.All(c => c == Character || IsFarEnough(c));
|
||||
}
|
||||
else
|
||||
{
|
||||
canAttack = Character.CharacterList.All(c => c == Character || !Character.IsFriendly(c) || IsFarEnough(c));
|
||||
}
|
||||
if (canAttack)
|
||||
{
|
||||
canAttack = !IsBlocked(attackSimPos) && !IsBlocked(AttackLimb.SimPosition + forward * ConvertUnits.ToSimUnits(AttackLimb.attack.Range));
|
||||
|
||||
bool IsBlocked(Vector2 targetPosition)
|
||||
foreach (var body in Submarine.PickBodies(AttackLimb.SimPosition, targetPosition, myBodies, Physics.CollisionCharacter))
|
||||
{
|
||||
foreach (var body in Submarine.PickBodies(AttackLimb.SimPosition, targetPosition, myBodies, Physics.CollisionCharacter))
|
||||
Character hitTarget = null;
|
||||
if (body.UserData is Character c)
|
||||
{
|
||||
Character hitTarget = null;
|
||||
if (body.UserData is Character c)
|
||||
{
|
||||
hitTarget = c;
|
||||
}
|
||||
else if (body.UserData is Limb limb)
|
||||
{
|
||||
hitTarget = limb.character;
|
||||
}
|
||||
if (hitTarget != null && !hitTarget.IsDead && Character.IsFriendly(hitTarget))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
hitTarget = c;
|
||||
}
|
||||
else if (body.UserData is Limb limb)
|
||||
{
|
||||
hitTarget = limb.character;
|
||||
}
|
||||
if (hitTarget != null && !hitTarget.IsDead && Character.IsFriendly(hitTarget))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1854,7 +1837,33 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (!canAttack || distance > Math.Min(AttackLimb.attack.Range * 0.9f, 100))
|
||||
if (AttackLimb is Limb attackLimb && attackLimb.attack.Ranged)
|
||||
{
|
||||
bool advance = !canAttack && Character.InWater || distance > attackLimb.attack.Range * 0.9f;
|
||||
bool fallBack = canAttack && distance < Math.Min(250, attackLimb.attack.Range * 0.25f);
|
||||
if (fallBack)
|
||||
{
|
||||
Reverse = true;
|
||||
UpdateFallBack(attackWorldPos, deltaTime, followThrough: false);
|
||||
}
|
||||
else if (advance)
|
||||
{
|
||||
if (pathSteering != null)
|
||||
{
|
||||
pathSteering.SteeringSeek(steerPos, weight: 10, minGapWidth: minGapSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
SteeringManager.SteeringSeek(steerPos, 10);
|
||||
}
|
||||
}
|
||||
else if (!Character.InWater)
|
||||
{
|
||||
SteeringManager.Reset();
|
||||
FaceTarget(SelectedAiTarget.Entity);
|
||||
}
|
||||
}
|
||||
else if (!canAttack || distance > Math.Min(AttackLimb.attack.Range * 0.9f, 100))
|
||||
{
|
||||
if (pathSteering != null)
|
||||
{
|
||||
@@ -1865,20 +1874,30 @@ namespace Barotrauma
|
||||
SteeringManager.SteeringSeek(steerPos, 10);
|
||||
}
|
||||
}
|
||||
else if (AttackLimb.attack.Ranged)
|
||||
{
|
||||
// Too close
|
||||
UpdateFallBack(attackWorldPos, deltaTime, followThrough: false);
|
||||
}
|
||||
|
||||
if (Character.CurrentHull == null && (SelectedAiTarget?.Entity is Character c && c.Submarine == null || distance == 0 || distance > ConvertUnits.ToDisplayUnits(avoidLookAheadDistance * 2)))
|
||||
{
|
||||
SteeringManager.SteeringAvoid(deltaTime, lookAheadDistance: avoidLookAheadDistance, weight: 30);
|
||||
}
|
||||
}
|
||||
}
|
||||
IDamageable damageTarget = wallTarget != null ? wallTarget.Structure : SelectedAiTarget?.Entity as IDamageable;
|
||||
if (AttackLimb?.attack is Attack { Ranged: true} attack)
|
||||
{
|
||||
Limb limb = GetLimbToRotate(attack);
|
||||
if (limb != null)
|
||||
{
|
||||
Vector2 toTarget = damageTarget.WorldPosition - limb.WorldPosition;
|
||||
float offset = limb.Params.GetSpriteOrientation() - MathHelper.PiOver2;
|
||||
limb.body.SuppressSmoothRotationCalls = false;
|
||||
float angle = MathUtils.VectorToAngle(toTarget);
|
||||
limb.body.SmoothRotate(angle + offset, attack.AimRotationTorque);
|
||||
limb.body.SuppressSmoothRotationCalls = true;
|
||||
}
|
||||
}
|
||||
if (canAttack)
|
||||
{
|
||||
if (!UpdateLimbAttack(deltaTime, AttackLimb, attackSimPos, distance, attackTargetLimb))
|
||||
if (!UpdateLimbAttack(deltaTime, attackSimPos, damageTarget, distance, attackTargetLimb))
|
||||
{
|
||||
IgnoreTarget(SelectedAiTarget);
|
||||
}
|
||||
@@ -2114,13 +2133,14 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
// 10 dmg, 100 health -> 0.1
|
||||
private float GetRelativeDamage(float dmg, float vitality) => dmg / Math.Max(vitality, 1.0f);
|
||||
private static float GetRelativeDamage(float dmg, float vitality) => dmg / Math.Max(vitality, 1.0f);
|
||||
|
||||
private bool UpdateLimbAttack(float deltaTime, Limb attackingLimb, Vector2 attackSimPos, float distance = -1, Limb targetLimb = null)
|
||||
private bool UpdateLimbAttack(float deltaTime, Vector2 attackSimPos, IDamageable damageTarget, float distance = -1, Limb targetLimb = null)
|
||||
{
|
||||
if (SelectedAiTarget?.Entity == null) { return false; }
|
||||
if (attackingLimb?.attack == null) { return false; }
|
||||
ActiveAttack = attackingLimb.attack;
|
||||
if (AttackLimb?.attack == null) { return false; }
|
||||
if (damageTarget == null) { return false; }
|
||||
ActiveAttack = AttackLimb.attack;
|
||||
if (wallTarget != null)
|
||||
{
|
||||
// If the selected target is not the wall target, make the wall target the selected target.
|
||||
@@ -2131,83 +2151,94 @@ namespace Barotrauma
|
||||
State = AIState.Attack;
|
||||
}
|
||||
}
|
||||
IDamageable damageTarget = wallTarget != null ? wallTarget.Structure : SelectedAiTarget.Entity as IDamageable;
|
||||
if (damageTarget != null)
|
||||
if (damageTarget == null) { return false; }
|
||||
if (ActiveAttack.Ranged && ActiveAttack.RequiredAngleToShoot > 0)
|
||||
{
|
||||
if (Character.Params.CanInteract && Character.Inventory != null)
|
||||
Limb referenceLimb = GetLimbToRotate(ActiveAttack);
|
||||
if (referenceLimb != null)
|
||||
{
|
||||
// Use equipped items (weapons)
|
||||
Item item = GetEquippedItem(attackingLimb);
|
||||
if (item != null)
|
||||
Vector2 toTarget = damageTarget.WorldPosition - referenceLimb.WorldPosition;
|
||||
float offset = referenceLimb.Params.GetSpriteOrientation() - MathHelper.PiOver2;
|
||||
Vector2 forward = VectorExtensions.Forward(referenceLimb.body.TransformedRotation - offset * referenceLimb.Dir);
|
||||
float angle = MathHelper.ToDegrees(VectorExtensions.Angle(forward, toTarget));
|
||||
if (angle > ActiveAttack.RequiredAngleToShoot)
|
||||
{
|
||||
if (item.RequireAimToUse)
|
||||
{
|
||||
if (!Aim(deltaTime, damageTarget as ISpatialEntity, item))
|
||||
{
|
||||
// Valid target, but can't shoot -> return true so that it will not be ignored.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Character.SetInput(item.IsShootable ? InputType.Shoot : InputType.Use, false, true);
|
||||
item.Use(deltaTime, Character);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//simulate attack input to get the character to attack client-side
|
||||
Character.SetInput(InputType.Attack, true, true);
|
||||
if (!ActiveAttack.IsRunning)
|
||||
}
|
||||
if (Character.Params.CanInteract && Character.Inventory != null)
|
||||
{
|
||||
// Use equipped items (weapons)
|
||||
Item item = GetEquippedItem(AttackLimb);
|
||||
if (item != null)
|
||||
{
|
||||
if (item.RequireAimToUse)
|
||||
{
|
||||
if (!Aim(deltaTime, damageTarget as ISpatialEntity, item))
|
||||
{
|
||||
// Valid target, but can't shoot -> return true so that it will not be ignored.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Character.SetInput(item.IsShootable ? InputType.Shoot : InputType.Use, false, true);
|
||||
item.Use(deltaTime, Character);
|
||||
}
|
||||
}
|
||||
//simulate attack input to get the character to attack client-side
|
||||
Character.SetInput(InputType.Attack, true, true);
|
||||
if (!ActiveAttack.IsRunning)
|
||||
{
|
||||
#if SERVER
|
||||
GameMain.NetworkMember.CreateEntityEvent(Character, new Character.SetAttackTargetEventData(
|
||||
attackingLimb,
|
||||
AttackLimb,
|
||||
damageTarget,
|
||||
targetLimb,
|
||||
SimPosition));
|
||||
#else
|
||||
Character.PlaySound(CharacterSound.SoundType.Attack, maxInterval: 3);
|
||||
Character.PlaySound(CharacterSound.SoundType.Attack, maxInterval: 3);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (attackingLimb.UpdateAttack(deltaTime, attackSimPos, damageTarget, out AttackResult attackResult, distance, targetLimb))
|
||||
if (AttackLimb.UpdateAttack(deltaTime, attackSimPos, damageTarget, out AttackResult attackResult, distance, targetLimb))
|
||||
{
|
||||
if (ActiveAttack.CoolDownTimer > 0)
|
||||
{
|
||||
if (attackingLimb.attack.CoolDownTimer > 0)
|
||||
SetAimTimer(Math.Min(ActiveAttack.CoolDown, 1.5f));
|
||||
// Managed to hit a living/non-destroyed target. Increase the priority more if the target is low in health -> dies easily/soon
|
||||
float greed = AIParams.AggressionGreed;
|
||||
if (damageTarget is not Barotrauma.Character)
|
||||
{
|
||||
// Halve the greed for attacking non-characters.
|
||||
greed /= 2;
|
||||
}
|
||||
selectedTargetMemory.Priority += GetRelativeDamage(attackResult.Damage, damageTarget.Health) * greed;
|
||||
}
|
||||
if (LatchOntoAI != null && SelectedAiTarget.Entity is Character targetCharacter)
|
||||
{
|
||||
LatchOntoAI.SetAttachTarget(targetCharacter);
|
||||
}
|
||||
if (!ActiveAttack.Ranged)
|
||||
{
|
||||
if (damageTarget.Health > 0 && attackResult.Damage > 0)
|
||||
{
|
||||
SetAimTimer(Math.Min(attackingLimb.attack.CoolDown, 1.5f));
|
||||
// Managed to hit a living/non-destroyed target. Increase the priority more if the target is low in health -> dies easily/soon
|
||||
float greed = AIParams.AggressionGreed;
|
||||
if (!(damageTarget is Character))
|
||||
if (damageTarget is not Barotrauma.Character)
|
||||
{
|
||||
// Halve the greed for attacking non-characters.
|
||||
greed /= 2;
|
||||
}
|
||||
selectedTargetMemory.Priority += GetRelativeDamage(attackResult.Damage, damageTarget.Health) * greed;
|
||||
}
|
||||
if (LatchOntoAI != null && SelectedAiTarget.Entity is Character targetCharacter)
|
||||
else
|
||||
{
|
||||
LatchOntoAI.SetAttachTarget(targetCharacter);
|
||||
}
|
||||
if (!attackingLimb.attack.Ranged)
|
||||
{
|
||||
if (damageTarget.Health > 0 && attackResult.Damage > 0)
|
||||
{
|
||||
// Managed to hit a living/non-destroyed target. Increase the priority more if the target is low in health -> dies easily/soon
|
||||
float greed = AIParams.AggressionGreed;
|
||||
if (!(damageTarget is Character))
|
||||
{
|
||||
// Halve the greed for attacking non-characters.
|
||||
greed /= 2;
|
||||
}
|
||||
selectedTargetMemory.Priority += GetRelativeDamage(attackResult.Damage, damageTarget.Health) * greed;
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedTargetMemory.Priority -= Math.Max(selectedTargetMemory.Priority / 2, 1);
|
||||
return selectedTargetMemory.Priority > 1;
|
||||
}
|
||||
selectedTargetMemory.Priority -= Math.Max(selectedTargetMemory.Priority / 2, 1);
|
||||
return selectedTargetMemory.Priority > 1;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private float aimTimer;
|
||||
@@ -2299,7 +2330,6 @@ namespace Barotrauma
|
||||
{
|
||||
if (attackVector == null)
|
||||
{
|
||||
// TODO: test adding some random variance here?
|
||||
attackVector = attackWorldPos - WorldPosition;
|
||||
}
|
||||
Vector2 dir = Vector2.Normalize(followThrough ? attackVector.Value : -attackVector.Value);
|
||||
@@ -2319,6 +2349,16 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
|
||||
private Limb GetLimbToRotate(Attack attack)
|
||||
{
|
||||
Limb limb = AttackLimb;
|
||||
if (attack.RotationLimbIndex > -1 && attack.RotationLimbIndex < Character.AnimController.Limbs.Length)
|
||||
{
|
||||
limb = Character.AnimController.Limbs[attack.RotationLimbIndex];
|
||||
}
|
||||
return limb;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Eat
|
||||
@@ -3429,7 +3469,7 @@ namespace Barotrauma
|
||||
private void ChangeParams(string tag, AIState state, float? priority = null, bool onlyExisting = false)
|
||||
=> ChangeParams(tag.ToIdentifier(), state, priority, onlyExisting);
|
||||
|
||||
private void ChangeParams(Identifier tag, AIState state, float? priority = null, bool onlyExisting = false)
|
||||
private void ChangeParams(Identifier tag, AIState state, float? priority = null, bool onlyExisting = false, bool ignoreAttacksIfNotInSameSub = false)
|
||||
{
|
||||
if (!AIParams.TryGetTarget(tag, out CharacterParams.TargetParams targetParams))
|
||||
{
|
||||
@@ -3437,6 +3477,11 @@ namespace Barotrauma
|
||||
{
|
||||
if (AIParams.TryAddNewTarget(tag, state, priority ?? minPriority, out targetParams))
|
||||
{
|
||||
if (state == AIState.Attack)
|
||||
{
|
||||
// Only applies to new temp target params. Shouldn't affect any existing definitions (handled below).
|
||||
targetParams.IgnoreIfNotInSameSub = ignoreAttacksIfNotInSameSub;
|
||||
}
|
||||
tempParams.Add(tag, targetParams);
|
||||
}
|
||||
}
|
||||
@@ -3470,7 +3515,7 @@ namespace Barotrauma
|
||||
{
|
||||
isStateChanged = true;
|
||||
SetStateResetTimer();
|
||||
ChangeParams(target.SpeciesName, state, priority);
|
||||
ChangeParams(target.SpeciesName, state, priority, ignoreAttacksIfNotInSameSub: !target.IsHuman);
|
||||
if (target.IsHuman)
|
||||
{
|
||||
priority = GetTargetParams("human")?.Priority;
|
||||
|
||||
+4
-1
@@ -748,6 +748,9 @@ namespace Barotrauma
|
||||
}
|
||||
if (!character.HasEquippedItem(Weapon, predicate: IsHandSlotType))
|
||||
{
|
||||
//clear aim and shoot inputs so the bot doesn't immediately fire the weapon if it was previously e.g. using a scooter
|
||||
character.ClearInput(InputType.Aim);
|
||||
character.ClearInput(InputType.Shoot);
|
||||
Weapon.TryInteract(character, forceSelectKey: true);
|
||||
var slots = Weapon.AllowedSlots.Where(s => IsHandSlotType(s));
|
||||
if (character.Inventory.TryPutItem(Weapon, character, slots))
|
||||
@@ -764,7 +767,7 @@ namespace Barotrauma
|
||||
}
|
||||
return true;
|
||||
|
||||
bool IsHandSlotType(InvSlotType s) => s == InvSlotType.LeftHand || s == InvSlotType.RightHand || s == (InvSlotType.LeftHand | InvSlotType.RightHand);
|
||||
static bool IsHandSlotType(InvSlotType s) => s == InvSlotType.LeftHand || s == InvSlotType.RightHand || s == (InvSlotType.LeftHand | InvSlotType.RightHand);
|
||||
}
|
||||
|
||||
private float findHullTimer;
|
||||
|
||||
+2
-2
@@ -186,8 +186,8 @@ namespace Barotrauma
|
||||
{
|
||||
if (character.SelectedItem != Item)
|
||||
{
|
||||
if (Item.TryInteract(character, ignoreRequiredItems: true, forceSelectKey: true) ||
|
||||
Item.TryInteract(character, ignoreRequiredItems: true, forceUseKey: true))
|
||||
if (Item.TryInteract(character, ignoreRequiredItems: true, forceUseKey: true) ||
|
||||
Item.TryInteract(character, ignoreRequiredItems: true, forceSelectKey: true))
|
||||
{
|
||||
character.SelectedItem = Item;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using static Barotrauma.CharacterParams;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -44,7 +45,7 @@ namespace Barotrauma
|
||||
public float PlayTimer { get; set; }
|
||||
private float? unstunY { get; set; }
|
||||
|
||||
public EnemyAIController AiController { get; private set; } = null;
|
||||
public EnemyAIController AIController { get; private set; } = null;
|
||||
|
||||
public Character Owner { get; set; }
|
||||
|
||||
@@ -134,8 +135,8 @@ namespace Barotrauma
|
||||
aggregate += Items[i].Commonness;
|
||||
if (aggregate >= r && Items[i].Prefab != null)
|
||||
{
|
||||
GameAnalyticsManager.AddDesignEvent("MicroInteraction:" + (GameMain.GameSession?.GameMode?.Preset.Identifier.Value ?? "null") + ":PetProducedItem:" + pet.AiController.Character.SpeciesName + ":" + Items[i].Prefab.Identifier);
|
||||
Entity.Spawner.AddItemToSpawnQueue(Items[i].Prefab, pet.AiController.Character.WorldPosition);
|
||||
GameAnalyticsManager.AddDesignEvent("MicroInteraction:" + (GameMain.GameSession?.GameMode?.Preset.Identifier.Value ?? "null") + ":PetProducedItem:" + pet.AIController.Character.SpeciesName + ":" + Items[i].Prefab.Identifier);
|
||||
Entity.Spawner.AddItemToSpawnQueue(Items[i].Prefab, pet.AIController.Character.WorldPosition);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -160,8 +161,8 @@ namespace Barotrauma
|
||||
|
||||
public PetBehavior(XElement element, EnemyAIController aiController)
|
||||
{
|
||||
AiController = aiController;
|
||||
AiController.Character.CanBeDragged = true;
|
||||
AIController = aiController;
|
||||
AIController.Character.CanBeDragged = true;
|
||||
|
||||
MaxHappiness = element.GetAttributeFloat("maxhappiness", 100.0f);
|
||||
MaxHunger = element.GetAttributeFloat("maxhunger", 100.0f);
|
||||
@@ -218,7 +219,7 @@ namespace Barotrauma
|
||||
bool success = OnEat(item.GetTags());
|
||||
if (success)
|
||||
{
|
||||
GameAnalyticsManager.AddDesignEvent("MicroInteraction:" + (GameMain.GameSession?.GameMode?.Preset.Identifier.Value ?? "null") + ":PetEat:" + AiController.Character.SpeciesName + ":" + item.Prefab.Identifier);
|
||||
GameAnalyticsManager.AddDesignEvent("MicroInteraction:" + (GameMain.GameSession?.GameMode?.Preset.Identifier.Value ?? "null") + ":PetEat:" + AIController.Character.SpeciesName + ":" + item.Prefab.Identifier);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
@@ -229,7 +230,7 @@ namespace Barotrauma
|
||||
bool success = OnEat("dead".ToIdentifier());
|
||||
if (success)
|
||||
{
|
||||
GameAnalyticsManager.AddDesignEvent("MicroInteraction:" + (GameMain.GameSession?.GameMode?.Preset.Identifier.Value ?? "null") + ":PetEat:" + AiController.Character.SpeciesName + ":" + character.SpeciesName);
|
||||
GameAnalyticsManager.AddDesignEvent("MicroInteraction:" + (GameMain.GameSession?.GameMode?.Preset.Identifier.Value ?? "null") + ":PetEat:" + AIController.Character.SpeciesName + ":" + character.SpeciesName);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
@@ -252,7 +253,7 @@ namespace Barotrauma
|
||||
Hunger += foods[i].Hunger;
|
||||
Happiness += foods[i].Happiness;
|
||||
#if CLIENT
|
||||
AiController.Character.PlaySound(CharacterSound.SoundType.Happy, 0.5f);
|
||||
AIController.Character.PlaySound(CharacterSound.SoundType.Happy, 0.5f);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@@ -265,20 +266,20 @@ namespace Barotrauma
|
||||
if (PlayTimer > 0.0f) { return; }
|
||||
if (Owner == null) { Owner = player; }
|
||||
PlayTimer = 5.0f;
|
||||
AiController.Character.IsRagdolled = true;
|
||||
AIController.Character.IsRagdolled = true;
|
||||
Happiness += 10.0f;
|
||||
AiController.Character.AnimController.MainLimb.body.LinearVelocity += new Vector2(0, PlayForce);
|
||||
unstunY = AiController.Character.SimPosition.Y;
|
||||
AIController.Character.AnimController.MainLimb.body.LinearVelocity += new Vector2(0, PlayForce);
|
||||
unstunY = AIController.Character.SimPosition.Y;
|
||||
#if CLIENT
|
||||
AiController.Character.PlaySound(CharacterSound.SoundType.Happy, 0.9f);
|
||||
AIController.Character.PlaySound(CharacterSound.SoundType.Happy, 0.9f);
|
||||
#endif
|
||||
}
|
||||
|
||||
public string GetTagName()
|
||||
{
|
||||
if (AiController.Character.Inventory != null)
|
||||
if (AIController.Character.Inventory != null)
|
||||
{
|
||||
foreach (Item item in AiController.Character.Inventory.AllItems)
|
||||
foreach (Item item in AIController.Character.Inventory.AllItems)
|
||||
{
|
||||
var tag = item.GetComponent<NameTag>();
|
||||
if (tag != null && !string.IsNullOrWhiteSpace(tag.WrittenName))
|
||||
@@ -293,7 +294,7 @@ namespace Barotrauma
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
var character = AiController.Character;
|
||||
var character = AIController.Character;
|
||||
if (character?.Removed ?? true || character.IsDead) { return; }
|
||||
|
||||
if (unstunY.HasValue)
|
||||
@@ -332,16 +333,27 @@ namespace Barotrauma
|
||||
Food food = foods[i];
|
||||
if (Hunger >= food.HungerRange.X && Hunger <= food.HungerRange.Y)
|
||||
{
|
||||
if (food.TargetParams == null &&
|
||||
AiController.AIParams.TryAddNewTarget(food.Tag, AIState.Eat, food.Priority, out CharacterParams.TargetParams targetParams))
|
||||
if (food.TargetParams == null)
|
||||
{
|
||||
targetParams.IgnoreContained = food.IgnoreContained;
|
||||
food.TargetParams = targetParams;
|
||||
if (AIController.AIParams.TryGetTarget(food.Tag, out TargetParams target))
|
||||
{
|
||||
food.TargetParams = target;
|
||||
}
|
||||
else if (AIController.AIParams.TryAddNewTarget(food.Tag, AIState.Eat, food.Priority, out TargetParams targetParams))
|
||||
{
|
||||
food.TargetParams = targetParams;
|
||||
}
|
||||
if (food.TargetParams != null)
|
||||
{
|
||||
food.TargetParams.State = AIState.Eat;
|
||||
food.TargetParams.Priority = food.Priority;
|
||||
food.TargetParams.IgnoreContained = food.IgnoreContained;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (food.TargetParams != null)
|
||||
{
|
||||
AiController.AIParams.RemoveTarget(food.TargetParams);
|
||||
AIController.AIParams.RemoveTarget(food.TargetParams);
|
||||
food.TargetParams = null;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -116,10 +116,10 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
// accept only the highest priority order
|
||||
if (CurrentOrder != null && OrderedCharacter.GetCurrentOrderWithTopPriority() != CurrentOrder)
|
||||
if (CurrentOrder == null || OrderedCharacter.GetCurrentOrderWithTopPriority() != CurrentOrder)
|
||||
{
|
||||
#if DEBUG
|
||||
ShipCommandManager.ShipCommandLog($"Order {CurrentOrder.Name} did not match current order for character {OrderedCharacter} in {this}");
|
||||
ShipCommandManager.ShipCommandLog($"{this} is no longer the top priority of {OrderedCharacter}, considering the issue unattended.");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -356,7 +356,7 @@ namespace Barotrauma
|
||||
ShipIssueWorkers.Add(new ShipIssueWorkerSteer(this, order));
|
||||
}
|
||||
|
||||
foreach (Item item in CommandedSubmarine.GetItems(true).FindAll(i => i.HasTag("turret")))
|
||||
foreach (Item item in CommandedSubmarine.GetItems(true).FindAll(i => i.HasTag("turret") && !i.HasTag("hardpoint")))
|
||||
{
|
||||
var order = new Order(OrderPrefab.Prefabs["operateweapons"], item, item.GetComponent<Turret>());
|
||||
ShipIssueWorkers.Add(new ShipIssueWorkerOperateWeapons(this, order));
|
||||
|
||||
Reference in New Issue
Block a user