Unstable 0.17.7.0

This commit is contained in:
Markus Isberg
2022-04-08 00:34:17 +09:00
parent 95764d1fa8
commit 164d72ae3a
82 changed files with 852 additions and 385 deletions
@@ -62,9 +62,9 @@ namespace Barotrauma
private float enemycheckTimer;
/// <summary>
/// How far other characters can hear reports done by this character (e.g. reports for fires, intruders).
/// How far other characters can hear reports done by this character (e.g. reports for fires, intruders). Defaults to infinity.
/// </summary>
public float ReportRange { get; set; }
public float ReportRange { get; set; } = float.PositiveInfinity;
private float _aimSpeed = 1;
public float AimSpeed
@@ -166,7 +166,6 @@ namespace Barotrauma
objectiveManager = new AIObjectiveManager(c);
reactTimer = GetReactionTime();
SortTimer = Rand.Range(0f, sortObjectiveInterval);
ReportRange = Character.IsOnPlayerTeam ? float.PositiveInfinity : 1000;
}
public override void Update(float deltaTime)
@@ -269,6 +269,18 @@ namespace Barotrauma
if (!character.AnimController.InWater || character.Submarine != null) { return; }
if (CurrentPath == null || CurrentPath.Unreachable || CurrentPath.Finished) { return; }
if (CurrentPath.CurrentIndex < 0 || CurrentPath.CurrentIndex >= CurrentPath.Nodes.Count - 1) { return; }
var lastNode = CurrentPath.Nodes.Last();
Submarine targetSub = lastNode.Submarine;
if (targetSub != null)
{
float subSize = Math.Max(targetSub.Borders.Size.X, targetSub.Borders.Size.Y) / 2;
float margin = 500;
if (Vector2.DistanceSquared(character.WorldPosition, targetSub.WorldPosition) < MathUtils.Pow2(subSize + margin))
{
// Don't skip nodes when close to the target submarine.
return;
}
}
// Check if we could skip ahead to NextNode when the character is swimming and using waypoints outside.
// Do this to optimize the old path before creating and evaluating a new path.
// In general, this is to avoid behavior where:
@@ -280,7 +292,7 @@ namespace Barotrauma
{
var waypoint = CurrentPath.Nodes[i];
float directDistance = Vector2.DistanceSquared(character.WorldPosition, waypoint.WorldPosition);
if (directDistance > (pathDistance * pathDistance) || Submarine.PickBody(host.SimPosition, waypoint.SimPosition, collisionCategory: Physics.CollisionLevel | Physics.CollisionWall) != null)
if (directDistance > MathUtils.Pow2(pathDistance) || !character.CanSeeTarget(waypoint))
{
pathDistance -= CurrentPath.GetLength(startIndex: i - 1, endIndex: i);
continue;
@@ -336,6 +348,7 @@ namespace Barotrauma
return Vector2.Zero;
}
Vector2 pos = host.WorldPosition;
Vector2 diff = currentPath.CurrentNode.WorldPosition - pos;
bool isDiving = character.AnimController.InWater && character.AnimController.HeadInWater;
// Only humanoids can climb ladders
bool canClimb = character.AnimController is HumanoidAnimController && !character.LockHands;
@@ -346,7 +359,7 @@ namespace Barotrauma
}
Ladder nextLadder = GetNextLadder();
var ladders = currentLadder ?? nextLadder;
bool useLadders = canClimb && ladders != null && (!isDiving || Math.Abs(steering.X) < 0.1f && steering.Y > 1);
bool useLadders = canClimb && ladders != null && steering.LengthSquared() > 0.1f && (!isDiving || steering.Y > 1);
if (useLadders && character.SelectedConstruction != ladders.Item)
{
if (character.CanInteractWith(ladders.Item))
@@ -374,7 +387,6 @@ namespace Barotrauma
}
if (character.IsClimbing && useLadders)
{
Vector2 diff = currentPath.CurrentNode.WorldPosition - pos;
bool nextLadderSameAsCurrent = IsNextLadderSameAsCurrent;
if (nextLadderSameAsCurrent || currentLadder != null && nextLadder != null && Math.Abs(currentLadder.Item.Position.X - nextLadder.Item.Position.X) < 50)
{
@@ -398,7 +410,7 @@ namespace Barotrauma
else if (nextLadder != null && !nextLadderSameAsCurrent)
{
// Try to change the ladder (hatches between two submarines)
if (character.SelectedConstruction != nextLadder.Item && nextLadder.Item.IsInsideTrigger(character.WorldPosition))
if (character.SelectedConstruction != nextLadder.Item && character.CanInteractWith(nextLadder.Item))
{
if (nextLadder.Item.TryInteract(character, forceSelectKey: true))
{
@@ -406,7 +418,7 @@ namespace Barotrauma
}
}
}
if (isAboveFloor || nextLadderSameAsCurrent)
if (isAboveFloor || nextLadderSameAsCurrent || nextLadder == null && Math.Abs(diff.Y) < 10)
{
NextNode(!doorsChecked);
}
@@ -484,7 +496,7 @@ namespace Barotrauma
{
return Vector2.Zero;
}
return ConvertUnits.ToSimUnits(currentPath.CurrentNode.WorldPosition - pos);
return ConvertUnits.ToSimUnits(diff);
}
private void NextNode(bool checkDoors)
@@ -212,10 +212,14 @@ namespace Barotrauma
protected override bool CheckObjectiveSpecific()
{
if (sqrDistance > maxDistance * maxDistance)
if (character.Submarine == null || character.Submarine.TeamID != CharacterTeamType.FriendlyNPC)
{
// The target escaped from us.
return true;
// Can't lose the target in friendly outposts.
if (sqrDistance > maxDistance * maxDistance)
{
// The target escaped from us.
return true;
}
}
return IsEnemyDisabled || (AllowCoolDown && coolDownTimer <= 0);
}
@@ -101,7 +101,7 @@ namespace Barotrauma
{
if (InWater || !CanWalk)
{
return TargetMovement.LengthSquared() > SwimSlowParams.MovementSpeed;
return TargetMovement.LengthSquared() > MathUtils.Pow2(SwimSlowParams.MovementSpeed);
}
else
{
@@ -302,7 +302,7 @@ namespace Barotrauma
}
// used for talents/ability conditions
public Item SourceItem { get; }
public Item SourceItem { get; set; }
public List<Affliction> GetMultipliedAfflictions(float multiplier)
{
@@ -308,6 +308,10 @@ namespace Barotrauma
public bool IsHumanoid => Params.Humanoid;
public bool IsHusk => Params.Husk;
public bool IsMale => info?.IsMale ?? false;
public bool IsFemale => info?.IsFemale ?? false;
public string BloodDecalName => Params.BloodDecal;
public bool CanSpeak
@@ -557,10 +561,11 @@ namespace Barotrauma
#if CLIENT
CharacterHealth.SetHealthBarVisibility(value == null);
#elif SERVER
if (value is { IsDead: true, Wallet: { Balance: var balance } grabbedWallet })
if (value is { IsDead: true, Wallet: { Balance: var balance } grabbedWallet } && balance > 0)
{
Wallet.Give(balance);
grabbedWallet.Deduct(balance);
GameServer.Log($"{Name} grabbed {value.Name}'s body and received {grabbedWallet.Balance} mk.", ServerLog.MessageType.Money);
}
#endif
}
@@ -3587,21 +3592,8 @@ namespace Barotrauma
float attackImpulse = attack.TargetImpulse + attack.TargetForce * attack.ImpactMultiplier * deltaTime;
AbilityAttackData attackData = new AbilityAttackData(attack, this);
if (attacker != null)
{
attackData.Attacker = attacker;
attacker.CheckTalents(AbilityEffectType.OnAttack, attackData);
CheckTalents(AbilityEffectType.OnAttacked, attackData);
attackData.DamageMultiplier *= 1 + attacker.GetStatValue(StatTypes.AttackMultiplier);
if (attacker.TeamID == TeamID)
{
attackData.DamageMultiplier *= 1 + attacker.GetStatValue(StatTypes.TeamAttackMultiplier);
}
}
AbilityAttackData attackData = new AbilityAttackData(attack, this, attacker);
IEnumerable<Affliction> attackAfflictions;
if (attackData.Afflictions != null)
{
attackAfflictions = attackData.Afflictions.Union(attack.Afflictions.Keys);
@@ -4916,10 +4908,21 @@ namespace Barotrauma
public Character Character { get; set; }
public Character Attacker { get; set; }
public AbilityAttackData(Attack sourceAttack, Character character)
public AbilityAttackData(Attack sourceAttack, Character target, Character attacker)
{
SourceAttack = sourceAttack;
Character = character;
Character = target;
if (attacker != null)
{
Attacker = attacker;
attacker.CheckTalents(AbilityEffectType.OnAttack, this);
target.CheckTalents(AbilityEffectType.OnAttacked, this);
DamageMultiplier *= 1 + attacker.GetStatValue(StatTypes.AttackMultiplier);
if (attacker.TeamID == target.TeamID)
{
DamageMultiplier *= 1 + attacker.GetStatValue(StatTypes.TeamAttackMultiplier);
}
}
}
}
@@ -130,17 +130,22 @@ namespace Barotrauma
head = value;
HeadSprite = null;
AttachmentSprites = null;
IsMale = value.Preset?.TagSet?.Contains("Male".ToIdentifier()) ?? false;
IsFemale = value.Preset?.TagSet?.Contains("Female".ToIdentifier()) ?? false;
}
}
}
public bool IsMale { get; private set; }
public bool IsFemale { get; private set; }
public CharacterInfoPrefab Prefab => CharacterPrefab.Prefabs[SpeciesName].CharacterInfoPrefab;
public class HeadPreset : ISerializableEntity
{
private readonly CharacterInfoPrefab characterInfoPrefab;
public Identifier MenuCategory => TagSet.First(t => characterInfoPrefab.VarTags[characterInfoPrefab.MenuCategoryVar].Contains(t));
public ImmutableHashSet<Identifier> TagSet { get; private set; }
[Serialize("", IsPropertySaveable.No)]