Unstable 0.1500.7.0 (No edition)
This commit is contained in:
@@ -103,6 +103,9 @@ namespace Barotrauma
|
||||
!pathSteering.CurrentPath.Unreachable &&
|
||||
(!requireNonDirty || !pathSteering.IsPathDirty);
|
||||
|
||||
public bool IsCurrentPathUnreachable => steeringManager is IndoorsSteeringManager pathSteering && !pathSteering.IsPathDirty && pathSteering.CurrentPath != null && pathSteering.CurrentPath.Unreachable;
|
||||
public bool IsCurrentPathFinished => steeringManager is IndoorsSteeringManager pathSteering && !pathSteering.IsPathDirty && pathSteering.CurrentPath != null && pathSteering.CurrentPath.Finished;
|
||||
|
||||
protected readonly float colliderWidth;
|
||||
protected readonly float minGapSize;
|
||||
protected readonly float colliderLength;
|
||||
@@ -412,7 +415,7 @@ namespace Barotrauma
|
||||
}
|
||||
else if (EscapeTarget != null && EscapeTarget.FlowTargetHull != Character.CurrentHull)
|
||||
{
|
||||
if (pathSteering.CurrentPath != null && !pathSteering.IsPathDirty && pathSteering.CurrentPath.Unreachable)
|
||||
if (IsCurrentPathUnreachable)
|
||||
{
|
||||
unreachableGaps.Add(EscapeTarget);
|
||||
EscapeTarget = null;
|
||||
|
||||
@@ -453,7 +453,7 @@ namespace Barotrauma
|
||||
if (SelectedAiTarget?.Entity != null || EscapeTarget != null)
|
||||
{
|
||||
Entity t = SelectedAiTarget?.Entity ?? EscapeTarget;
|
||||
float referencePos = Vector2.DistanceSquared(Character.WorldPosition, t.WorldPosition) > 100 * 100 && HasValidPath(true) ? PathSteering.CurrentPath.CurrentNode.WorldPosition.X : t.WorldPosition.X;
|
||||
float referencePos = Vector2.DistanceSquared(Character.WorldPosition, t.WorldPosition) > 100 * 100 && HasValidPath(requireNonDirty: true) ? PathSteering.CurrentPath.CurrentNode.WorldPosition.X : t.WorldPosition.X;
|
||||
Character.AnimController.TargetDir = Character.WorldPosition.X < referencePos ? Direction.Right : Direction.Left;
|
||||
}
|
||||
else
|
||||
@@ -916,9 +916,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (SteeringManager is IndoorsSteeringManager pathSteering)
|
||||
{
|
||||
if (patrolTarget == null ||
|
||||
pathSteering.CurrentPath == null ||
|
||||
!pathSteering.IsPathDirty && (pathSteering.CurrentPath.Finished || pathSteering.CurrentPath.Unreachable))
|
||||
if (patrolTarget == null || IsCurrentPathUnreachable || IsCurrentPathFinished)
|
||||
{
|
||||
newPatrolTargetTimer = Math.Min(newPatrolTargetTimer, newPatrolTargetIntervalMin);
|
||||
}
|
||||
@@ -936,8 +934,7 @@ namespace Barotrauma
|
||||
else if (targetHulls.Any())
|
||||
{
|
||||
patrolTarget = ToolBox.SelectWeightedRandom(targetHulls, hullWeights, Rand.RandSync.Unsynced);
|
||||
var path = PathSteering.PathFinder.FindPath(Character.SimPosition, patrolTarget.SimPosition, minGapSize: minGapSize * 1.5f, nodeFilter: n => PatrolNodeFilter(n));
|
||||
|
||||
var path = PathSteering.PathFinder.FindPath(Character.SimPosition, patrolTarget.SimPosition, Character.Submarine, minGapSize: minGapSize * 1.5f, nodeFilter: n => PatrolNodeFilter(n));
|
||||
if (path.Unreachable)
|
||||
{
|
||||
//can't go to this room, remove it from the list and try another room
|
||||
@@ -2331,34 +2328,32 @@ namespace Barotrauma
|
||||
SelectedAiTarget.Entity is Character c && VisibleHulls.Contains(c.CurrentHull))
|
||||
{
|
||||
// Steer towards the target if in the same room and swimming
|
||||
Vector2 dir = Vector2.Normalize(SelectedAiTarget.Entity.WorldPosition - Character.WorldPosition);
|
||||
if (MathUtils.IsValid(dir))
|
||||
{
|
||||
SteeringManager.SteeringManual(deltaTime, dir);
|
||||
}
|
||||
SteeringManager.SteeringManual(deltaTime, Vector2.Normalize(SelectedAiTarget.Entity.WorldPosition - Character.WorldPosition));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use path finding
|
||||
PathSteering.SteeringSeek(Character.GetRelativeSimPosition(SelectedAiTarget.Entity), weight: 2, minGapWidth: minGapSize);
|
||||
if (!PathSteering.IsPathDirty && PathSteering.CurrentPath.Unreachable)
|
||||
{
|
||||
// Can't reach
|
||||
State = AIState.Idle;
|
||||
IgnoreTarget(SelectedAiTarget);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Outside
|
||||
SteeringManager.SteeringSeek(Character.GetRelativeSimPosition(SelectedAiTarget.Entity), 5);
|
||||
if (Character.AnimController.InWater)
|
||||
}
|
||||
if (steeringManager is IndoorsSteeringManager pathSteering)
|
||||
{
|
||||
if (!pathSteering.IsPathDirty && pathSteering.CurrentPath.Unreachable)
|
||||
{
|
||||
SteeringManager.SteeringAvoid(deltaTime, lookAheadDistance: avoidLookAheadDistance, weight: 15);
|
||||
// Can't reach
|
||||
State = AIState.Idle;
|
||||
IgnoreTarget(SelectedAiTarget);
|
||||
}
|
||||
}
|
||||
else if (Character.AnimController.InWater)
|
||||
{
|
||||
SteeringManager.SteeringAvoid(deltaTime, lookAheadDistance: avoidLookAheadDistance, weight: 15);
|
||||
}
|
||||
}
|
||||
|
||||
#region Targeting
|
||||
@@ -2510,6 +2505,11 @@ namespace Barotrauma
|
||||
else if (targetingFromOutsideToInside)
|
||||
{
|
||||
targetingTag = "room";
|
||||
if (item.Submarine?.Info.IsRuin != null)
|
||||
{
|
||||
// Ignore ruin items when the creature is outside.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (targetingTag == "nasonov")
|
||||
|
||||
@@ -115,6 +115,11 @@ namespace Barotrauma
|
||||
IsPathDirty = true;
|
||||
}
|
||||
|
||||
public void SteeringSeekSimple(Vector2 targetSimPos, float weight = 1)
|
||||
{
|
||||
steering += base.DoSteeringSeek(targetSimPos, weight);
|
||||
}
|
||||
|
||||
public void SteeringSeek(Vector2 target, float weight, float minGapWidth = 0, Func<PathNode, bool> startNodeFilter = null, Func<PathNode, bool> endNodeFilter = null, Func<PathNode, bool> nodeFilter = null, bool checkVisiblity = true)
|
||||
{
|
||||
steering += CalculateSteeringSeek(target, weight, minGapWidth, startNodeFilter, endNodeFilter, nodeFilter, checkVisiblity);
|
||||
@@ -164,7 +169,7 @@ namespace Barotrauma
|
||||
|
||||
private Vector2 CalculateSteeringSeek(Vector2 target, float weight, float minGapSize = 0, Func<PathNode, bool> startNodeFilter = null, Func<PathNode, bool> endNodeFilter = null, Func<PathNode, bool> nodeFilter = null, bool checkVisibility = true)
|
||||
{
|
||||
bool needsNewPath = currentPath == null || currentPath.Unreachable;
|
||||
bool needsNewPath = currentPath == null || currentPath.Unreachable || currentPath.Finished;
|
||||
if (!needsNewPath && character.Submarine != null && character.Params.PathFinderPriority > 0.5f)
|
||||
{
|
||||
Vector2 targetDiff = target - currentTarget;
|
||||
@@ -194,16 +199,8 @@ namespace Barotrauma
|
||||
SkipCurrentPathNodes();
|
||||
currentTarget = target;
|
||||
Vector2 currentPos = host.SimPosition;
|
||||
if (character != null && character.Submarine == null)
|
||||
{
|
||||
var targetHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(target), null, false);
|
||||
if (targetHull != null && targetHull.Submarine != null)
|
||||
{
|
||||
currentPos -= targetHull.Submarine.SimPosition;
|
||||
}
|
||||
}
|
||||
pathFinder.InsideSubmarine = character.Submarine != null;
|
||||
pathFinder.ApplyPenaltyToOutsideNodes = character.PressureProtection <= 0;
|
||||
pathFinder.InsideSubmarine = character.Submarine != null && !character.Submarine.Info.IsRuin;
|
||||
pathFinder.ApplyPenaltyToOutsideNodes = character.Submarine != null && character.PressureProtection <= 0;
|
||||
var newPath = pathFinder.FindPath(currentPos, target, character.Submarine, "(Character: " + character.Name + ")", minGapSize, startNodeFilter, endNodeFilter, nodeFilter, checkVisibility: checkVisibility);
|
||||
bool useNewPath = needsNewPath || currentPath == null || currentPath.CurrentNode == null || character.Submarine != null && findPathTimer < -1 && Math.Abs(character.AnimController.TargetMovement.X) <= 0;
|
||||
if (!useNewPath && currentPath != null && currentPath.CurrentNode != null && newPath.Nodes.Any() && !newPath.Unreachable)
|
||||
@@ -218,7 +215,7 @@ namespace Barotrauma
|
||||
// Use the new path if it has significantly lower cost (don't change the path if it has marginally smaller cost. This reduces navigating backwards due to new path that is calculated from the node just behind us).
|
||||
float t = (float)currentPath.CurrentIndex / (currentPath.Nodes.Count - 1);
|
||||
useNewPath = newPath.Cost < currentPath.Cost * MathHelper.Lerp(0.95f, 0, t);
|
||||
if (!useNewPath && character.Submarine != null)
|
||||
if (!useNewPath)
|
||||
{
|
||||
// It's possible that the current path was calculated from a start point that is no longer valid.
|
||||
// Therefore, let's accept also paths with a greater cost than the current, if the current node is much farther than the new start node.
|
||||
@@ -322,15 +319,26 @@ namespace Barotrauma
|
||||
doorsChecked = true;
|
||||
}
|
||||
Vector2 pos = host.SimPosition;
|
||||
if (character != null && CurrentPath.CurrentNode?.Submarine != null)
|
||||
if (character != null && CurrentPath.CurrentNode != null)
|
||||
{
|
||||
if (character.Submarine == null)
|
||||
var nodeSub = CurrentPath.CurrentNode.Submarine;
|
||||
if (nodeSub != null)
|
||||
{
|
||||
pos -= CurrentPath.CurrentNode.Submarine.SimPosition;
|
||||
if (character.Submarine == null)
|
||||
{
|
||||
// Going inside
|
||||
pos -= ConvertUnits.ToSimUnits(nodeSub.Position);
|
||||
}
|
||||
else if (character.Submarine != nodeSub)
|
||||
{
|
||||
// Different subs
|
||||
pos -= ConvertUnits.ToSimUnits(nodeSub.Position - character.Submarine.Position);
|
||||
}
|
||||
}
|
||||
else if (character.Submarine != currentPath.CurrentNode.Submarine)
|
||||
else if (character.Submarine != null)
|
||||
{
|
||||
pos -= ConvertUnits.ToSimUnits(currentPath.CurrentNode.Submarine.Position - character.Submarine.Position);
|
||||
// Going outside
|
||||
pos += ConvertUnits.ToSimUnits(character.Submarine.Position);
|
||||
}
|
||||
}
|
||||
bool isDiving = character.AnimController.InWater && character.AnimController.HeadInWater;
|
||||
|
||||
+5
-1
@@ -724,7 +724,10 @@ namespace Barotrauma
|
||||
}
|
||||
if (retreatTarget != null && character.CurrentHull != retreatTarget)
|
||||
{
|
||||
TryAddSubObjective(ref retreatObjective, () => new AIObjectiveGoTo(retreatTarget, character, objectiveManager, false, true),
|
||||
TryAddSubObjective(ref retreatObjective, () => new AIObjectiveGoTo(retreatTarget, character, objectiveManager, false, true)
|
||||
{
|
||||
UsePathingOutside = false
|
||||
},
|
||||
onAbandon: () =>
|
||||
{
|
||||
if (Enemy != null && HumanAIController.VisibleHulls.Contains(Enemy.CurrentHull))
|
||||
@@ -783,6 +786,7 @@ namespace Barotrauma
|
||||
TryAddSubObjective(ref followTargetObjective,
|
||||
constructor: () => new AIObjectiveGoTo(Enemy, character, objectiveManager, repeat: true, getDivingGearIfNeeded: true, closeEnough: 50)
|
||||
{
|
||||
UsePathingOutside = false,
|
||||
IgnoreIfTargetDead = true,
|
||||
DialogueIdentifier = "dialogcannotreachtarget",
|
||||
TargetName = Enemy.DisplayName,
|
||||
|
||||
+1
-1
@@ -334,7 +334,7 @@ namespace Barotrauma
|
||||
continue;
|
||||
}
|
||||
// Don't allow to go outside if not already outside.
|
||||
var path = PathSteering.PathFinder.FindPath(character.SimPosition, hull.SimPosition, nodeFilter: node => node.Waypoint.CurrentHull != null);
|
||||
var path = PathSteering.PathFinder.FindPath(character.SimPosition, hull.SimPosition, character.Submarine, nodeFilter: node => node.Waypoint.CurrentHull != null);
|
||||
if (path.Unreachable)
|
||||
{
|
||||
HumanAIController.UnreachableHulls.Add(hull);
|
||||
|
||||
+1
-1
@@ -323,7 +323,7 @@ namespace Barotrauma
|
||||
// This is relatively expensive, so let's do this only when it significantly improves the behavior.
|
||||
// Only allow one path find call per frame.
|
||||
hasCalledPathFinder = true;
|
||||
var path = PathSteering.PathFinder.FindPath(character.SimPosition, item.SimPosition, errorMsgStr: $"AIObjectiveGetItem {character.DisplayName}", nodeFilter: node => node.Waypoint.CurrentHull != null);
|
||||
var path = PathSteering.PathFinder.FindPath(character.SimPosition, item.SimPosition, character.Submarine, errorMsgStr: $"AIObjectiveGetItem {character.DisplayName}", nodeFilter: node => node.Waypoint.CurrentHull != null);
|
||||
if (path.Unreachable) { continue; }
|
||||
}
|
||||
currItemPriority = itemPriority;
|
||||
|
||||
+44
-31
@@ -27,6 +27,7 @@ namespace Barotrauma
|
||||
public bool followControlledCharacter;
|
||||
public bool mimic;
|
||||
public bool SpeakIfFails { get; set; } = true;
|
||||
public bool UsePathingOutside { get; set; } = true;
|
||||
|
||||
public float extraDistanceWhileSwimming;
|
||||
public float extraDistanceOutsideSub;
|
||||
@@ -121,13 +122,14 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
private readonly float avoidLookAheadDistance = 5;
|
||||
private readonly float pathWaitingTime = 3;
|
||||
|
||||
public AIObjectiveGoTo(ISpatialEntity target, Character character, AIObjectiveManager objectiveManager, bool repeat = false, bool getDivingGearIfNeeded = true, float priorityModifier = 1, float closeEnough = 0)
|
||||
: base(character, objectiveManager, priorityModifier)
|
||||
{
|
||||
Target = target;
|
||||
this.repeat = repeat;
|
||||
waitUntilPathUnreachable = 3.0f;
|
||||
waitUntilPathUnreachable = pathWaitingTime;
|
||||
this.getDivingGearIfNeeded = getDivingGearIfNeeded;
|
||||
if (Target is Item i)
|
||||
{
|
||||
@@ -186,7 +188,6 @@ namespace Barotrauma
|
||||
// Wait
|
||||
character.AIController.SteeringManager.Reset();
|
||||
}
|
||||
waitUntilPathUnreachable -= deltaTime;
|
||||
if (!character.IsClimbing)
|
||||
{
|
||||
character.SelectedConstruction = null;
|
||||
@@ -222,11 +223,13 @@ namespace Barotrauma
|
||||
{
|
||||
Abandon = true;
|
||||
}
|
||||
else if (SteeringManager == PathSteering && PathSteering.CurrentPath != null && PathSteering.CurrentPath.Unreachable && !PathSteering.IsPathDirty)
|
||||
else if (HumanAIController.IsCurrentPathUnreachable)
|
||||
{
|
||||
waitUntilPathUnreachable -= deltaTime;
|
||||
SteeringManager.Reset();
|
||||
if (waitUntilPathUnreachable < 0)
|
||||
{
|
||||
waitUntilPathUnreachable = pathWaitingTime;
|
||||
if (repeat)
|
||||
{
|
||||
SpeakCannotReach();
|
||||
@@ -325,25 +328,29 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
SeekGaps(maxGapDistance);
|
||||
seekGapsTimer = seekGapsInterval * Rand.Range(0.1f, 1.1f);
|
||||
if (TargetGap != null)
|
||||
bool isRuins = character.Submarine?.Info.IsRuin != null || Target.Submarine?.Info.IsRuin != null;
|
||||
if (!isRuins || !HumanAIController.HasValidPath(requireNonDirty: true, requireUnfinished: true))
|
||||
{
|
||||
// Check that nothing is blocking the way
|
||||
Vector2 rayStart = character.SimPosition;
|
||||
Vector2 rayEnd = TargetGap.SimPosition;
|
||||
if (TargetGap.Submarine != null && character.Submarine == null)
|
||||
SeekGaps(maxGapDistance);
|
||||
seekGapsTimer = seekGapsInterval * Rand.Range(0.1f, 1.1f);
|
||||
if (TargetGap != null)
|
||||
{
|
||||
rayStart -= TargetGap.Submarine.SimPosition;
|
||||
}
|
||||
else if (TargetGap.Submarine == null && character.Submarine != null)
|
||||
{
|
||||
rayEnd -= character.Submarine.SimPosition;
|
||||
}
|
||||
var closestBody = Submarine.CheckVisibility(rayStart, rayEnd, ignoreSubs: true);
|
||||
if (closestBody != null)
|
||||
{
|
||||
TargetGap = null;
|
||||
// Check that nothing is blocking the way
|
||||
Vector2 rayStart = character.SimPosition;
|
||||
Vector2 rayEnd = TargetGap.SimPosition;
|
||||
if (TargetGap.Submarine != null && character.Submarine == null)
|
||||
{
|
||||
rayStart -= TargetGap.Submarine.SimPosition;
|
||||
}
|
||||
else if (TargetGap.Submarine == null && character.Submarine != null)
|
||||
{
|
||||
rayEnd -= character.Submarine.SimPosition;
|
||||
}
|
||||
var closestBody = Submarine.CheckVisibility(rayStart, rayEnd, ignoreSubs: true);
|
||||
if (closestBody != null)
|
||||
{
|
||||
TargetGap = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -454,19 +461,25 @@ namespace Barotrauma
|
||||
}
|
||||
else if (!isInside && HumanAIController.UseIndoorSteeringOutside)
|
||||
{
|
||||
if (character.Submarine == null && Target.Submarine != null)
|
||||
{
|
||||
targetPos += Target.Submarine.SimPosition;
|
||||
}
|
||||
nodeFilter = n => n.Waypoint.Tunnel != null;
|
||||
nodeFilter = n => n.Waypoint.Submarine == null;
|
||||
}
|
||||
|
||||
PathSteering.SteeringSeek(targetPos, weight: 1,
|
||||
startNodeFilter: n => (n.Waypoint.CurrentHull == null) == (character.CurrentHull == null),
|
||||
endNodeFilter: endNodeFilter,
|
||||
nodeFilter: nodeFilter,
|
||||
checkVisiblity: CheckVisibility);
|
||||
|
||||
if (!isInside && !UsePathingOutside)
|
||||
{
|
||||
PathSteering.SteeringSeekSimple(character.GetRelativeSimPosition(Target), 10);
|
||||
if (character.AnimController.InWater)
|
||||
{
|
||||
SteeringManager.SteeringAvoid(deltaTime, avoidLookAheadDistance, weight: 15);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PathSteering.SteeringSeek(targetPos, weight: 1,
|
||||
startNodeFilter: n => (n.Waypoint.CurrentHull == null) == (character.CurrentHull == null),
|
||||
endNodeFilter: endNodeFilter,
|
||||
nodeFilter: nodeFilter,
|
||||
checkVisiblity: CheckVisibility);
|
||||
}
|
||||
if (!isInside && (PathSteering.CurrentPath == null || PathSteering.IsPathDirty || PathSteering.CurrentPath.Unreachable))
|
||||
{
|
||||
if (useScooter)
|
||||
|
||||
+1
-1
@@ -251,7 +251,7 @@ namespace Barotrauma
|
||||
currentTarget = ToolBox.SelectWeightedRandom(targetHulls, hullWeights, Rand.RandSync.Unsynced);
|
||||
bool isInWrongSub = (character.TeamID == CharacterTeamType.FriendlyNPC && !character.IsEscorted) && character.Submarine.TeamID != character.TeamID;
|
||||
bool isCurrentHullAllowed = !isInWrongSub && !IsForbidden(character.CurrentHull);
|
||||
var path = PathSteering.PathFinder.FindPath(character.SimPosition, currentTarget.SimPosition, errorMsgStr: null, nodeFilter: node =>
|
||||
var path = PathSteering.PathFinder.FindPath(character.SimPosition, currentTarget.SimPosition, character.Submarine, nodeFilter: node =>
|
||||
{
|
||||
if (node.Waypoint.CurrentHull == null) { return false; }
|
||||
// Check that there is no unsafe hulls on the way to the target
|
||||
|
||||
+16
-20
@@ -1,7 +1,6 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -69,7 +68,7 @@ namespace Barotrauma
|
||||
HumanAIController.ResetEscape();
|
||||
}
|
||||
HumanAIController.Escape(deltaTime);
|
||||
if (HumanAIController.EscapeTarget == null || !HumanAIController.HasValidPath(requireNonDirty: true, requireUnfinished: false))
|
||||
if (HumanAIController.EscapeTarget == null || HumanAIController.IsCurrentPathUnreachable)
|
||||
{
|
||||
Abandon = true;
|
||||
}
|
||||
@@ -92,14 +91,16 @@ namespace Barotrauma
|
||||
{
|
||||
RemoveSubObjective(ref moveInCaveObjective);
|
||||
RemoveSubObjective(ref moveOutsideObjective);
|
||||
// TODO: Check 'repeat' and 'onAbandon' parameters
|
||||
TryAddSubObjective(ref moveInsideObjective,
|
||||
constructor: () => new AIObjectiveGoTo(targetHull, character, objectiveManager),
|
||||
onCompleted: () => moveInsideObjective = null);
|
||||
onCompleted: () => RemoveSubObjective(ref moveInsideObjective),
|
||||
onAbandon: () => Abandon = true);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("Error with a Return objective: no suitable target for 'moveInsideObjective'");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,8 +118,7 @@ namespace Barotrauma
|
||||
float closestDistance = float.MaxValue;
|
||||
foreach (var w in WayPoint.WayPointList)
|
||||
{
|
||||
if (w.Tunnel == null) { continue; }
|
||||
if (w.Tunnel.Type == Level.TunnelType.Cave) { continue; }
|
||||
if (w.Tunnel != null && w.Tunnel.Type == Level.TunnelType.Cave) { continue; }
|
||||
if (w.linkedTo.None(l => l is WayPoint linkedWaypoint && linkedWaypoint.Tunnel?.Type == Level.TunnelType.Cave)) { continue; }
|
||||
float distance = Vector2.DistanceSquared(character.WorldPosition, w.WorldPosition);
|
||||
if (closestOutsideWaypoint == null || distance < closestDistance)
|
||||
@@ -131,17 +131,19 @@ namespace Barotrauma
|
||||
{
|
||||
RemoveSubObjective(ref moveInsideObjective);
|
||||
RemoveSubObjective(ref moveOutsideObjective);
|
||||
// TODO: Check 'repeat' and 'onAbandon' parameters
|
||||
TryAddSubObjective(ref moveInCaveObjective,
|
||||
constructor: () => new AIObjectiveGoTo(closestOutsideWaypoint, character, objectiveManager)
|
||||
{
|
||||
endNodeFilter = n => n.Waypoint == closestOutsideWaypoint
|
||||
},
|
||||
onCompleted: () => moveInCaveObjective = null);
|
||||
onCompleted: () => RemoveSubObjective(ref moveInCaveObjective),
|
||||
onAbandon: () => Abandon = true);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("Error with a Return objective: no suitable main or side path node target found for 'moveOutsideObjective'");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -167,14 +169,16 @@ namespace Barotrauma
|
||||
{
|
||||
RemoveSubObjective(ref moveInsideObjective);
|
||||
RemoveSubObjective(ref moveInCaveObjective);
|
||||
// TODO: Check 'repeat' and 'onAbandon' parameters
|
||||
TryAddSubObjective(ref moveOutsideObjective,
|
||||
constructor: () => new AIObjectiveGoTo(targetHull, character, objectiveManager),
|
||||
onCompleted: () => moveOutsideObjective = null);
|
||||
onCompleted: () => RemoveSubObjective(ref moveOutsideObjective),
|
||||
onAbandon: () => Abandon = true);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("Error with a Return objective: no suitable target for 'moveOutsideObjective'");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -182,19 +186,11 @@ namespace Barotrauma
|
||||
{
|
||||
if (HumanAIController.IsInsideCave)
|
||||
{
|
||||
if (moveOutsideObjective != null)
|
||||
{
|
||||
RemoveSubObjective(ref moveOutsideObjective);
|
||||
moveOutsideObjective = null;
|
||||
}
|
||||
RemoveSubObjective(ref moveOutsideObjective);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (moveInCaveObjective != null)
|
||||
{
|
||||
RemoveSubObjective(ref moveInCaveObjective);
|
||||
moveInCaveObjective = null;
|
||||
}
|
||||
RemoveSubObjective(ref moveInCaveObjective);
|
||||
}
|
||||
}
|
||||
usingEscapeBehavior = shouldUseEscapeBehavior;
|
||||
|
||||
@@ -119,7 +119,8 @@ namespace Barotrauma
|
||||
|
||||
public PathFinder(List<WayPoint> wayPoints, bool isCharacter)
|
||||
{
|
||||
nodes = PathNode.GenerateNodes(wayPoints.FindAll(w => (w.Submarine != null == isCharacter) || (isCharacter && w.Tunnel != null)), removeOrphans: true);
|
||||
var filtered = isCharacter ? wayPoints : wayPoints.FindAll(w => w.Submarine == null);
|
||||
nodes = PathNode.GenerateNodes(filtered, removeOrphans: true);
|
||||
foreach (WayPoint wp in wayPoints)
|
||||
{
|
||||
wp.OnLinksChanged += WaypointLinksChanged;
|
||||
@@ -179,17 +180,37 @@ namespace Barotrauma
|
||||
foreach (PathNode node in nodes)
|
||||
{
|
||||
node.TempPosition = node.Position;
|
||||
if (hostSub != null)
|
||||
var wpSub = node.Waypoint.Submarine;
|
||||
if (hostSub != null && wpSub == null)
|
||||
{
|
||||
Vector2 diff = node.Waypoint.Submarine != null ?
|
||||
hostSub.SimPosition - node.Waypoint.Submarine.SimPosition :
|
||||
hostSub.SimPosition - node.Waypoint.SimPosition;
|
||||
node.TempPosition -= diff;
|
||||
// inside and targeting outside
|
||||
node.TempPosition -= hostSub.SimPosition;
|
||||
}
|
||||
else if (wpSub != null && hostSub != null && wpSub != hostSub)
|
||||
{
|
||||
// different subs
|
||||
node.TempPosition -= hostSub.SimPosition - wpSub.SimPosition;
|
||||
}
|
||||
else if (hostSub == null && wpSub != null)
|
||||
{
|
||||
// Outside and targeting inside
|
||||
node.TempPosition += wpSub.SimPosition;
|
||||
}
|
||||
float xDiff = Math.Abs(start.X - node.TempPosition.X);
|
||||
float yDiff = Math.Abs(start.Y - node.TempPosition.Y);
|
||||
if (yDiff > 1.0f && node.Waypoint.Ladders == null && node.Waypoint.Stairs == null) { yDiff += 10.0f; }
|
||||
node.TempDistance = xDiff + (InsideSubmarine ? yDiff * 10.0f : yDiff); //higher cost for vertical movement when inside the sub
|
||||
if (InsideSubmarine)
|
||||
{
|
||||
//higher cost for vertical movement when inside the sub
|
||||
if (yDiff > 1.0f && node.Waypoint.Ladders == null && node.Waypoint.Stairs == null)
|
||||
{
|
||||
yDiff += 10.0f;
|
||||
}
|
||||
node.TempDistance = xDiff + yDiff * 10.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
node.TempDistance = xDiff + yDiff;
|
||||
}
|
||||
|
||||
//much higher cost to waypoints that are outside
|
||||
if (node.Waypoint.CurrentHull == null && ApplyPenaltyToOutsideNodes) { node.TempDistance *= 10.0f; }
|
||||
|
||||
@@ -57,7 +57,10 @@ namespace Barotrauma
|
||||
|
||||
public void SteeringManual(float deltaTime, Vector2 velocity)
|
||||
{
|
||||
steering += velocity;
|
||||
if (MathUtils.IsValid(velocity))
|
||||
{
|
||||
steering += velocity;
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
|
||||
@@ -374,7 +374,7 @@ namespace Barotrauma
|
||||
{
|
||||
//pull the character's mouth to the target character (again with a fluctuating force)
|
||||
float pullStrength = (float)(Math.Sin(eatTimer) * Math.Max(Math.Sin(eatTimer * 0.5f), 0.0f));
|
||||
mouthLimb.body.ApplyForce(limbDiff * mouthLimb.Mass * 50.0f * pullStrength, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
mouthLimb.body.ApplyForce(limbDiff * mouthLimb.Mass * 50.0f * pullStrength);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+16
-9
@@ -746,7 +746,7 @@ namespace Barotrauma
|
||||
var arm = GetLimb(armType);
|
||||
if (arm != null && Math.Abs(arm.body.AngularVelocity) < 10.0f)
|
||||
{
|
||||
arm.body.SmoothRotate(MathHelper.Clamp(-arm.body.AngularVelocity, -0.5f, 0.5f), arm.Mass * 50.0f);
|
||||
arm.body.SmoothRotate(MathHelper.Clamp(-arm.body.AngularVelocity, -0.5f, 0.5f), arm.Mass * 50.0f * CurrentGroundedParams.ArmMoveStrength);
|
||||
}
|
||||
|
||||
//get the elbow to a neutral rotation
|
||||
@@ -757,7 +757,7 @@ namespace Barotrauma
|
||||
if (elbow != null)
|
||||
{
|
||||
float diff = elbow.JointAngle - (Dir > 0 ? elbow.LowerLimit : elbow.UpperLimit);
|
||||
forearm.body.ApplyTorque(MathHelper.Clamp(-diff, -MathHelper.PiOver2, MathHelper.PiOver2) * forearm.Mass * 100.0f);
|
||||
forearm.body.ApplyTorque(MathHelper.Clamp(-diff, -MathHelper.PiOver2, MathHelper.PiOver2) * forearm.Mass * 100.0f * CurrentGroundedParams.ArmMoveStrength);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -809,8 +809,8 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (Gap gap in currentHull.ConnectedGaps)
|
||||
{
|
||||
if (gap.IsHorizontal || gap.Open <= 0.0f) continue;
|
||||
if (Collider.SimPosition.X < ConvertUnits.ToSimUnits(gap.Rect.X) || Collider.SimPosition.X > ConvertUnits.ToSimUnits(gap.Rect.Right)) continue;
|
||||
if (gap.IsHorizontal || gap.Open <= 0.0f) { continue; }
|
||||
if (Collider.SimPosition.X < ConvertUnits.ToSimUnits(gap.Rect.X) || Collider.SimPosition.X > ConvertUnits.ToSimUnits(gap.Rect.Right)) { continue; }
|
||||
|
||||
//if the gap is above us and leads outside, there's no surface to limit the movement
|
||||
if (!gap.IsRoomToRoom && gap.Position.Y > currentHull.Position.Y)
|
||||
@@ -830,7 +830,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
surfaceLimiter = ConvertUnits.ToDisplayUnits(Collider.SimPosition.Y + 0.4f) - surfacePos;
|
||||
surfaceLimiter = ConvertUnits.ToDisplayUnits(Collider.SimPosition.Y + 1.0f) - surfacePos;
|
||||
surfaceLimiter = Math.Max(1.0f, surfaceLimiter);
|
||||
if (surfaceLimiter > 50.0f) { return; }
|
||||
}
|
||||
@@ -921,7 +921,7 @@ namespace Barotrauma
|
||||
head.body.ApplyTorque(Dir);
|
||||
}
|
||||
|
||||
movement.Y = movement.Y - (surfaceLimiter - 1.0f) * 0.01f;
|
||||
movement.Y = movement.Y * (1.0f - ((surfaceLimiter - 1.0f) / 50.0f));
|
||||
}
|
||||
|
||||
bool isNotRemote = true;
|
||||
@@ -1003,7 +1003,10 @@ namespace Barotrauma
|
||||
rightHandPos.X = (Dir == 1.0f) ? Math.Max(0.3f, rightHandPos.X) : Math.Min(-0.3f, rightHandPos.X);
|
||||
rightHandPos = Vector2.Transform(rightHandPos, rotationMatrix);
|
||||
float speedMultiplier = Math.Min(character.SpeedMultiplier * (1 - Character.GetRightHandPenalty()), 1.0f);
|
||||
// Limb hand, Vector2 pos, float force = 1.0f
|
||||
if (character.Inventory != null && character.Inventory.GetItemInLimbSlot(InvSlotType.RightHand) != null)
|
||||
{
|
||||
speedMultiplier = Math.Min(speedMultiplier, 0.1f);
|
||||
}
|
||||
HandIK(rightHand, handPos + rightHandPos, CurrentSwimParams.ArmMoveStrength * speedMultiplier, CurrentSwimParams.HandMoveStrength * speedMultiplier);
|
||||
}
|
||||
|
||||
@@ -1013,6 +1016,10 @@ namespace Barotrauma
|
||||
leftHandPos.X = (Dir == 1.0f) ? Math.Max(0.3f, leftHandPos.X) : Math.Min(-0.3f, leftHandPos.X);
|
||||
leftHandPos = Vector2.Transform(leftHandPos, rotationMatrix);
|
||||
float speedMultiplier = Math.Min(character.SpeedMultiplier * (1 - Character.GetLeftHandPenalty()), 1.0f);
|
||||
if (character.Inventory != null && character.Inventory.GetItemInLimbSlot(InvSlotType.LeftHand) != null)
|
||||
{
|
||||
speedMultiplier = Math.Min(speedMultiplier, 0.1f);
|
||||
}
|
||||
HandIK(leftHand, handPos + leftHandPos, CurrentSwimParams.ArmMoveStrength * speedMultiplier, CurrentSwimParams.HandMoveStrength * speedMultiplier);
|
||||
}
|
||||
}
|
||||
@@ -1154,7 +1161,7 @@ namespace Barotrauma
|
||||
if (character.SimPosition.Y > ladderSimPos.Y) { climbForce.Y = Math.Min(0.0f, climbForce.Y); }
|
||||
|
||||
//apply forces to the collider to move the Character up/down
|
||||
Collider.ApplyForce((climbForce * 20.0f + subSpeed * 50.0f) * Collider.Mass, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
Collider.ApplyForce((climbForce * 20.0f + subSpeed * 50.0f) * Collider.Mass);
|
||||
float movementMultiplier = targetMovement.Y < 0 ? 0 : 1;
|
||||
head.body.SmoothRotate(MathHelper.PiOver4 * movementMultiplier * Dir, WalkParams.HeadTorque);
|
||||
|
||||
@@ -1383,7 +1390,7 @@ namespace Barotrauma
|
||||
target.CharacterHealth.CalculateVitality();
|
||||
if (wasCritical && target.Vitality > 0.0f && Timing.TotalTime > lastReviveTime + 10.0f)
|
||||
{
|
||||
character.Info?.IncreaseSkillLevel("medical", SkillSettings.Current.SkillIncreasePerCprRevive, character.Position + Vector2.UnitY * 150.0f);
|
||||
character.Info?.IncreaseSkillLevel("medical", SkillSettings.Current.SkillIncreasePerCprRevive);
|
||||
SteamAchievementManager.OnCharacterRevived(target, character);
|
||||
lastReviveTime = (float)Timing.TotalTime;
|
||||
#if SERVER
|
||||
|
||||
@@ -1348,19 +1348,19 @@ namespace Barotrauma
|
||||
string errorMsg = null;
|
||||
if (!MathUtils.IsValid(body.SimPosition) || Math.Abs(body.SimPosition.X) > 1e10f || Math.Abs(body.SimPosition.Y) > 1e10f)
|
||||
{
|
||||
errorMsg = GetBodyName() + " position invalid (" + body.SimPosition + ", character: " + character.Name + "), resetting the ragdoll.";
|
||||
errorMsg = GetBodyName() + " position invalid (" + body.SimPosition + ", character: " + character.Name + ").";
|
||||
}
|
||||
else if (!MathUtils.IsValid(body.LinearVelocity) || Math.Abs(body.LinearVelocity.X) > 1000f || Math.Abs(body.LinearVelocity.Y) > 1000f)
|
||||
{
|
||||
errorMsg = GetBodyName() + " velocity invalid (" + body.LinearVelocity + ", character: " + character.Name + "), resetting the ragdoll.";
|
||||
errorMsg = GetBodyName() + " velocity invalid (" + body.LinearVelocity + ", character: " + character.Name + ").";
|
||||
}
|
||||
else if (!MathUtils.IsValid(body.Rotation))
|
||||
{
|
||||
errorMsg = GetBodyName() + " rotation invalid (" + body.Rotation + ", character: " + character.Name + "), resetting the ragdoll.";
|
||||
errorMsg = GetBodyName() + " rotation invalid (" + body.Rotation + ", character: " + character.Name + ").";
|
||||
}
|
||||
else if (!MathUtils.IsValid(body.AngularVelocity) || Math.Abs(body.AngularVelocity) > 1000f)
|
||||
{
|
||||
errorMsg = GetBodyName() + " angular velocity invalid (" + body.AngularVelocity + ", character: " + character.Name + "), resetting the ragdoll.";
|
||||
errorMsg = GetBodyName() + " angular velocity invalid (" + body.AngularVelocity + ", character: " + character.Name + ").";
|
||||
}
|
||||
if (errorMsg != null)
|
||||
{
|
||||
@@ -1469,11 +1469,11 @@ namespace Barotrauma
|
||||
|
||||
if (flowForce.LengthSquared() > 0.001f)
|
||||
{
|
||||
Collider.ApplyForce(flowForce, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
Collider.ApplyForce(flowForce);
|
||||
foreach (Limb limb in limbs)
|
||||
{
|
||||
if (!limb.InWater) { continue; }
|
||||
limb.body.ApplyForce(flowForce, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
limb.body.ApplyForce(flowForce);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1506,7 +1506,6 @@ namespace Barotrauma
|
||||
if (TorsoPosition.HasValue && MathUtils.IsValid(TorsoPosition.Value)) { height = Math.Max(height, TorsoPosition.Value); }
|
||||
|
||||
Vector2 rayEnd = rayStart - new Vector2(0.0f, height);
|
||||
Vector2 onGroundRayEnd = rayStart - Vector2.UnitY * (Collider.height * 0.5f + Collider.radius + ColliderHeightFromFloor * 1.2f);
|
||||
Vector2 colliderBottomDisplay = ConvertUnits.ToDisplayUnits(GetColliderBottom());
|
||||
|
||||
Fixture standOnFloorFixture = null;
|
||||
@@ -1587,7 +1586,25 @@ namespace Barotrauma
|
||||
if (closestFraction == 1) //raycast didn't hit anything
|
||||
{
|
||||
floorNormal = Vector2.UnitY;
|
||||
return (currentHull == null) ? -1000.0f : ConvertUnits.ToSimUnits(currentHull.Rect.Y - currentHull.Rect.Height);
|
||||
if (CurrentHull == null)
|
||||
{
|
||||
return -1000.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
float hullBottom = currentHull.Rect.Y - currentHull.Rect.Height;
|
||||
//check if there's a connected hull below
|
||||
foreach (var gap in currentHull.ConnectedGaps)
|
||||
{
|
||||
if (!gap.IsRoomToRoom || gap.Open < 1.0f || gap.ConnectedDoor != null || gap.IsHorizontal) { continue; }
|
||||
if (WorldPosition.X > gap.WorldRect.X && WorldPosition.X < gap.WorldRect.Right && gap.WorldPosition.Y < WorldPosition.Y)
|
||||
{
|
||||
var lowerHull = gap.linkedTo[0] == currentHull ? gap.linkedTo[1] : gap.linkedTo[0];
|
||||
hullBottom = Math.Min(hullBottom, lowerHull.Rect.Y - lowerHull.Rect.Height);
|
||||
}
|
||||
}
|
||||
return ConvertUnits.ToSimUnits(hullBottom);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1745,8 +1745,12 @@ namespace Barotrauma
|
||||
}
|
||||
else if (IsKeyDown(InputType.Attack))
|
||||
{
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient)
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient && Controlled != this)
|
||||
{
|
||||
if ((currentAttackTarget.DamageTarget as Entity)?.Removed ?? false)
|
||||
{
|
||||
currentAttackTarget = default(AttackTargetData);
|
||||
}
|
||||
currentAttackTarget.AttackLimb?.UpdateAttack(deltaTime, currentAttackTarget.AttackPos, currentAttackTarget.DamageTarget, out _);
|
||||
}
|
||||
else if (IsPlayer)
|
||||
@@ -3670,16 +3674,14 @@ namespace Barotrauma
|
||||
{
|
||||
float attackerSkillLevel = attacker.GetSkillLevel("weapons");
|
||||
attacker.Info?.IncreaseSkillLevel("weapons",
|
||||
-healthChange * SkillSettings.Current.SkillIncreasePerHostileDamage / Math.Max(attackerSkillLevel, 1.0f),
|
||||
attacker.Position + Vector2.UnitY * 100.0f);
|
||||
-healthChange * SkillSettings.Current.SkillIncreasePerHostileDamage / Math.Max(attackerSkillLevel, 1.0f));
|
||||
}
|
||||
}
|
||||
else if (healthChange > 0.0f)
|
||||
{
|
||||
float attackerSkillLevel = attacker.GetSkillLevel("medical");
|
||||
attacker.Info?.IncreaseSkillLevel("medical",
|
||||
healthChange * SkillSettings.Current.SkillIncreasePerFriendlyHealed / Math.Max(attackerSkillLevel, 1.0f),
|
||||
attacker.Position + Vector2.UnitY * 100.0f);
|
||||
healthChange * SkillSettings.Current.SkillIncreasePerFriendlyHealed / Math.Max(attackerSkillLevel, 1.0f));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3927,7 +3929,7 @@ namespace Barotrauma
|
||||
}
|
||||
partial void KillProjSpecific(CauseOfDeathType causeOfDeath, Affliction causeOfDeathAffliction, bool log);
|
||||
|
||||
public void Revive()
|
||||
public void Revive(bool removeAllAfflictions = true)
|
||||
{
|
||||
if (Removed)
|
||||
{
|
||||
@@ -3938,7 +3940,14 @@ namespace Barotrauma
|
||||
aiTarget?.Remove();
|
||||
|
||||
aiTarget = new AITarget(this);
|
||||
CharacterHealth.RemoveAllAfflictions();
|
||||
if (removeAllAfflictions)
|
||||
{
|
||||
CharacterHealth.RemoveAllAfflictions();
|
||||
}
|
||||
else
|
||||
{
|
||||
CharacterHealth.RemoveNegativeAfflictions();
|
||||
}
|
||||
SetAllDamage(0.0f, 0.0f, 0.0f);
|
||||
Oxygen = 100.0f;
|
||||
Bloodloss = 0.0f;
|
||||
@@ -4284,12 +4293,8 @@ namespace Barotrauma
|
||||
}
|
||||
if (Submarine == null && target.Submarine != null)
|
||||
{
|
||||
if (AIController == null || !(AIController.SteeringManager is IndoorsSteeringManager))
|
||||
{
|
||||
// outside and targeting inside
|
||||
// doesn't work with inside steering
|
||||
targetPos += target.Submarine.SimPosition;
|
||||
}
|
||||
// outside and targeting inside
|
||||
targetPos += target.Submarine.SimPosition;
|
||||
}
|
||||
else if (Submarine != null && target.Submarine == null)
|
||||
{
|
||||
@@ -4376,14 +4381,14 @@ namespace Barotrauma
|
||||
|
||||
public bool GiveTalent(TalentPrefab talentPrefab, bool addingFirstTime = true)
|
||||
{
|
||||
if (addingFirstTime)
|
||||
{
|
||||
if (!info.UnlockedTalents.Add(talentPrefab.Identifier)) { return false; }
|
||||
}
|
||||
if (info == null) { return false; }
|
||||
info.UnlockedTalents.Add(talentPrefab.Identifier);
|
||||
if (characterTalents.Any(t => t.Prefab == talentPrefab)) { return false; }
|
||||
|
||||
CharacterTalent characterTalent = new CharacterTalent(talentPrefab, this);
|
||||
characterTalent.ActivateTalent(addingFirstTime);
|
||||
characterTalents.Add(characterTalent);
|
||||
characterTalent.AddedThisRound = addingFirstTime;
|
||||
|
||||
#if SERVER
|
||||
GameMain.NetworkMember.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.UpdateTalents });
|
||||
|
||||
@@ -1162,7 +1162,7 @@ namespace Barotrauma
|
||||
return (int)(salary * Job.Prefab.PriceMultiplier);
|
||||
}
|
||||
|
||||
public void IncreaseSkillLevel(string skillIdentifier, float increase, Vector2 pos, bool gainedFromApprenticeship = false)
|
||||
public void IncreaseSkillLevel(string skillIdentifier, float increase, bool gainedFromApprenticeship = false)
|
||||
{
|
||||
if (Job == null || (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) || Character == null) { return; }
|
||||
|
||||
@@ -1190,10 +1190,10 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
OnSkillChanged(skillIdentifier, prevLevel, newLevel, pos);
|
||||
OnSkillChanged(skillIdentifier, prevLevel, newLevel);
|
||||
}
|
||||
|
||||
public void SetSkillLevel(string skillIdentifier, float level, Vector2 pos)
|
||||
public void SetSkillLevel(string skillIdentifier, float level)
|
||||
{
|
||||
if (Job == null) { return; }
|
||||
|
||||
@@ -1201,19 +1201,19 @@ namespace Barotrauma
|
||||
if (skill == null)
|
||||
{
|
||||
Job.Skills.Add(new Skill(skillIdentifier, level));
|
||||
OnSkillChanged(skillIdentifier, 0.0f, level, pos);
|
||||
OnSkillChanged(skillIdentifier, 0.0f, level);
|
||||
}
|
||||
else
|
||||
{
|
||||
float prevLevel = skill.Level;
|
||||
skill.Level = level;
|
||||
OnSkillChanged(skillIdentifier, prevLevel, skill.Level, pos);
|
||||
OnSkillChanged(skillIdentifier, prevLevel, skill.Level);
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnSkillChanged(string skillIdentifier, float prevLevel, float newLevel, Vector2 textPopupPos);
|
||||
partial void OnSkillChanged(string skillIdentifier, float prevLevel, float newLevel);
|
||||
|
||||
public void GiveExperience(int amount, float popupOffset = 0f, bool isMissionExperience = false)
|
||||
public void GiveExperience(int amount, bool isMissionExperience = false)
|
||||
{
|
||||
int prevAmount = ExperiencePoints;
|
||||
|
||||
@@ -1229,7 +1229,7 @@ namespace Barotrauma
|
||||
if (amount < 0) { return; }
|
||||
|
||||
ExperiencePoints += amount;
|
||||
OnExperienceChanged(prevAmount, ExperiencePoints, Character.Position + Vector2.UnitY * (150.0f + popupOffset));
|
||||
OnExperienceChanged(prevAmount, ExperiencePoints);
|
||||
}
|
||||
|
||||
public void SetExperience(int newExperience)
|
||||
@@ -1238,7 +1238,7 @@ namespace Barotrauma
|
||||
|
||||
int prevAmount = ExperiencePoints;
|
||||
ExperiencePoints = newExperience;
|
||||
OnExperienceChanged(prevAmount, ExperiencePoints, Character.Position + Vector2.UnitY * 150.0f);
|
||||
OnExperienceChanged(prevAmount, ExperiencePoints);
|
||||
}
|
||||
|
||||
const int BaseExperienceRequired = 50;
|
||||
@@ -1295,7 +1295,7 @@ namespace Barotrauma
|
||||
return BaseExperienceRequired + AddedExperienceRequiredPerLevel * level;
|
||||
}
|
||||
|
||||
partial void OnExperienceChanged(int prevAmount, int newAmount, Vector2 textPopupPos);
|
||||
partial void OnExperienceChanged(int prevAmount, int newAmount);
|
||||
|
||||
public void Rename(string newName)
|
||||
{
|
||||
|
||||
@@ -206,7 +206,11 @@ namespace Barotrauma
|
||||
public float Stun
|
||||
{
|
||||
get { return stunAffliction.Strength; }
|
||||
set { stunAffliction.Strength = MathHelper.Clamp(value, 0.0f, stunAffliction.Prefab.MaxStrength); }
|
||||
set
|
||||
{
|
||||
if (Character.GodMode) { return; }
|
||||
stunAffliction.Strength = MathHelper.Clamp(value, 0.0f, stunAffliction.Prefab.MaxStrength);
|
||||
}
|
||||
}
|
||||
|
||||
public float StunTimer { get; private set; }
|
||||
@@ -629,6 +633,22 @@ namespace Barotrauma
|
||||
CalculateVitality();
|
||||
}
|
||||
|
||||
public void RemoveNegativeAfflictions()
|
||||
{
|
||||
// also don't remove genetic effects, even if they're negative
|
||||
foreach (LimbHealth limbHealth in limbHealths)
|
||||
{
|
||||
limbHealth.Afflictions.RemoveAll(a => !a.Prefab.IsBuff && a.Prefab.AfflictionType != "geneticmaterialbuff" && a.Prefab.AfflictionType != "geneticmaterialdebuff");
|
||||
}
|
||||
|
||||
afflictions.RemoveAll(a => !irremovableAfflictions.Contains(a) && !a.Prefab.IsBuff && a.Prefab.AfflictionType != "geneticmaterialbuff" && a.Prefab.AfflictionType != "geneticmaterialdebuff");
|
||||
foreach (Affliction affliction in irremovableAfflictions)
|
||||
{
|
||||
affliction.Strength = 0.0f;
|
||||
}
|
||||
CalculateVitality();
|
||||
}
|
||||
|
||||
private void AddLimbAffliction(Limb limb, Affliction newAffliction, bool allowStacking = true)
|
||||
{
|
||||
if (!newAffliction.Prefab.LimbSpecific || limb == null) { return; }
|
||||
|
||||
@@ -68,9 +68,20 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public class PreviewItem
|
||||
{
|
||||
public readonly string ItemIdentifier;
|
||||
public readonly bool ShowPreview;
|
||||
|
||||
public PreviewItem(string itemIdentifier, bool showPreview)
|
||||
{
|
||||
ItemIdentifier = itemIdentifier;
|
||||
ShowPreview = showPreview;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly Dictionary<int, XElement> ItemSets = new Dictionary<int, XElement>();
|
||||
public readonly Dictionary<int, List<string>> ItemIdentifiers = new Dictionary<int, List<string>>();
|
||||
public readonly Dictionary<int, Dictionary<string, bool>> ShowItemPreview = new Dictionary<int, Dictionary<string, bool>>();
|
||||
public readonly Dictionary<int, List<PreviewItem>> PreviewItems = new Dictionary<int, List<PreviewItem>>();
|
||||
public readonly List<SkillPrefab> Skills = new List<SkillPrefab>();
|
||||
public readonly List<AutonomousObjective> AutonomousObjectives = new List<AutonomousObjective>();
|
||||
public readonly List<string> AppropriateOrders = new List<string>();
|
||||
@@ -220,8 +231,7 @@ namespace Barotrauma
|
||||
{
|
||||
case "itemset":
|
||||
ItemSets.Add(variant, subElement);
|
||||
ItemIdentifiers[variant] = new List<string>();
|
||||
ShowItemPreview[variant] = new Dictionary<string, bool>();
|
||||
PreviewItems[variant] = new List<PreviewItem>();
|
||||
loadItemIdentifiers(subElement, variant);
|
||||
variant++;
|
||||
break;
|
||||
@@ -264,8 +274,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemIdentifiers[variant].Add(itemIdentifier);
|
||||
ShowItemPreview[variant][itemIdentifier] = itemElement.GetAttributeBool("showpreview", true);
|
||||
PreviewItems[variant].Add(new PreviewItem(itemIdentifier, itemElement.GetAttributeBool("showpreview", true)));
|
||||
}
|
||||
loadItemIdentifiers(itemElement, variant);
|
||||
}
|
||||
|
||||
@@ -759,6 +759,10 @@ namespace Barotrauma
|
||||
appliedDamageModifiers.AddRange(tempModifiers);
|
||||
}
|
||||
var result = new AttackResult(afflictionsCopy, this, appliedDamageModifiers);
|
||||
if (result.Afflictions.None())
|
||||
{
|
||||
playSound = false;
|
||||
}
|
||||
AddDamageProjSpecific(playSound, result);
|
||||
|
||||
float bleedingDamage = 0;
|
||||
|
||||
+6
-6
@@ -11,12 +11,12 @@ namespace Barotrauma
|
||||
{
|
||||
public enum AnimationType
|
||||
{
|
||||
NotDefined,
|
||||
Walk,
|
||||
Run,
|
||||
SwimSlow,
|
||||
SwimFast,
|
||||
Crouch
|
||||
NotDefined = 0,
|
||||
Walk = 1,
|
||||
Run = 2,
|
||||
Crouch = 3,
|
||||
SwimSlow = 4,
|
||||
SwimFast = 5
|
||||
}
|
||||
|
||||
abstract class GroundedMovementParams : AnimationParams
|
||||
|
||||
@@ -597,7 +597,7 @@ namespace Barotrauma
|
||||
[Serialize(float.NaN, true, description: "The orientation of the sprite as drawn on the sprite sheet. Overrides the value defined in the Ragdoll settings."), Editable(-360, 360, ValueStep = 90, DecimalCount = 0)]
|
||||
public float SpriteOrientation { get; set; }
|
||||
|
||||
[Serialize(LimbType.None, true, description: "If set, the limb sprite will use the same sprite depth as the specified limb. Generally only useful for limbs that get added on the ragdoll on the fly (e.g. extra limbs added via gene splicing).")]
|
||||
[Serialize(LimbType.None, true, description: "If set, the limb sprite will use the same sprite depth as the specified limb. Generally only useful for limbs that get added on the ragdoll on the fly (e.g. extra limbs added via gene splicing).")]
|
||||
public LimbType InheritLimbDepth { get; set; }
|
||||
|
||||
[Serialize(0f, true), Editable(MinValueFloat = 0, MaxValueFloat = 500)]
|
||||
|
||||
+11
-5
@@ -12,9 +12,12 @@ namespace Barotrauma.Abilities
|
||||
Ranged = 2
|
||||
};
|
||||
|
||||
private readonly bool hittingCountsAsAiming;
|
||||
|
||||
private readonly WeaponType weapontype;
|
||||
public AbilityConditionIsAiming(CharacterTalent characterTalent, XElement conditionElement) : base(characterTalent, conditionElement)
|
||||
{
|
||||
hittingCountsAsAiming = conditionElement.GetAttributeBool("hittingcountsasaiming", false);
|
||||
switch (conditionElement.GetAttributeString("weapontype", ""))
|
||||
{
|
||||
case "melee":
|
||||
@@ -28,7 +31,6 @@ namespace Barotrauma.Abilities
|
||||
|
||||
protected override bool MatchesConditionSpecific()
|
||||
{
|
||||
bool aimingCorrectItem = false;
|
||||
if (character.AnimController is HumanoidAnimController animController)
|
||||
{
|
||||
foreach (Item item in character.HeldItems)
|
||||
@@ -36,19 +38,23 @@ namespace Barotrauma.Abilities
|
||||
switch (weapontype)
|
||||
{
|
||||
case WeaponType.Melee:
|
||||
aimingCorrectItem |= item.GetComponent<MeleeWeapon>() != null && animController.IsAimingMelee;
|
||||
var meleeWeapon = item.GetComponent<MeleeWeapon>();
|
||||
if (meleeWeapon != null)
|
||||
{
|
||||
if (animController.IsAimingMelee || (meleeWeapon.Hitting && hittingCountsAsAiming)) { return true; }
|
||||
}
|
||||
break;
|
||||
case WeaponType.Ranged:
|
||||
aimingCorrectItem |= item.GetComponent<RangedWeapon>() != null && animController.IsAiming;
|
||||
if (animController.IsAiming && item.GetComponent<RangedWeapon>() != null) { return true; }
|
||||
break;
|
||||
default:
|
||||
aimingCorrectItem |= animController.IsAiming || animController.IsAimingMelee;
|
||||
if (animController.IsAiming || animController.IsAimingMelee) { return true; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return aimingCorrectItem;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ namespace Barotrauma.Abilities
|
||||
{
|
||||
if ((abilityObject as IAbilityValue)?.Value is float skillIncrease)
|
||||
{
|
||||
Character.Info?.IncreaseSkillLevel(skillIdentifier, skillIncrease, Character.Position + Vector2.UnitY * 175.0f);
|
||||
Character.Info?.IncreaseSkillLevel(skillIdentifier, skillIncrease);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Abilities
|
||||
{
|
||||
class CharacterAbilityGiveMissionCount : CharacterAbility
|
||||
{
|
||||
private readonly int amount;
|
||||
|
||||
public CharacterAbilityGiveMissionCount(CharacterAbilityGroup characterAbilityGroup, XElement abilityElement) : base(characterAbilityGroup, abilityElement)
|
||||
{
|
||||
amount = abilityElement.GetAttributeInt("amount", 0);
|
||||
}
|
||||
|
||||
public override void InitializeAbility(bool addingFirstTime)
|
||||
{
|
||||
if (!addingFirstTime) { return; }
|
||||
if (!(GameMain.GameSession?.Campaign is CampaignMode campaign)) { return; }
|
||||
campaign.Settings.AddedMissionCount += amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -49,13 +49,12 @@ namespace Barotrauma.Abilities
|
||||
{
|
||||
var skill = character.Info?.Job?.Skills?.GetRandom();
|
||||
if (skill == null) { return; }
|
||||
character.Info?.IncreaseSkillLevel(skill.Identifier, skillIncrease, character.Position + Vector2.UnitY * 175.0f);
|
||||
character.Info?.IncreaseSkillLevel(skill.Identifier, skillIncrease);
|
||||
}
|
||||
else
|
||||
{
|
||||
character.Info?.IncreaseSkillLevel(skillIdentifier, skillIncrease, character.Position + Vector2.UnitY * 175.0f);
|
||||
character.Info?.IncreaseSkillLevel(skillIdentifier, skillIncrease);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ namespace Barotrauma.Abilities
|
||||
|
||||
private void ApplyEffectSpecific()
|
||||
{
|
||||
Character.Revive();
|
||||
Character.Revive(removeAllAfflictions: false);
|
||||
}
|
||||
|
||||
protected override void ApplyEffect()
|
||||
|
||||
+1
@@ -21,6 +21,7 @@ namespace Barotrauma.Abilities
|
||||
{
|
||||
foreach (var talent in talentOption.Talents)
|
||||
{
|
||||
if (talent == CharacterTalent.Prefab) { continue; }
|
||||
Character.GiveTalent(talent);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ namespace Barotrauma.Abilities
|
||||
{
|
||||
if (abilityObject is AbilitySkillGain abilitySkillGain && !abilitySkillGain.GainedFromApprenticeship && abilitySkillGain.Character != Character)
|
||||
{
|
||||
Character.Info?.IncreaseSkillLevel(abilitySkillGain.String, 1.0f, Character.Position + Vector2.UnitY * 175.0f, gainedFromApprenticeship: true);
|
||||
Character.Info?.IncreaseSkillLevel(abilitySkillGain.String, 1.0f, gainedFromApprenticeship: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ namespace Barotrauma.Abilities
|
||||
if (skillIdentifier != lastSkillIdentifier)
|
||||
{
|
||||
lastSkillIdentifier = skillIdentifier;
|
||||
Character.Info?.IncreaseSkillLevel(skillIdentifier, 1.0f, Character.Position + Vector2.UnitY * 175.0f);
|
||||
Character.Info?.IncreaseSkillLevel(skillIdentifier, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ namespace Barotrauma
|
||||
|
||||
public readonly TalentPrefab Prefab;
|
||||
|
||||
public bool AddedThisRound = true;
|
||||
|
||||
private readonly Dictionary<AbilityEffectType, List<CharacterAbilityGroupEffect>> characterAbilityGroupEffectDictionary = new Dictionary<AbilityEffectType, List<CharacterAbilityGroupEffect>>();
|
||||
|
||||
private readonly List<CharacterAbilityGroupInterval> characterAbilityGroupIntervals = new List<CharacterAbilityGroupInterval>();
|
||||
|
||||
Reference in New Issue
Block a user