Unstable 0.15.11.0 + the last 2 unstables I missed
This commit is contained in:
@@ -426,30 +426,35 @@ namespace Barotrauma
|
||||
}
|
||||
if (EscapeTarget != null)
|
||||
{
|
||||
var door = EscapeTarget.ConnectedDoor;
|
||||
bool isClosedDoor = door != null && !door.IsOpen;
|
||||
Vector2 diff = EscapeTarget.WorldPosition - Character.WorldPosition;
|
||||
float sqrDist = diff.LengthSquared();
|
||||
if (Character.CurrentHull == null || sqrDist < MathUtils.Pow2(50) || pathSteering == null || IsCurrentPathUnreachable || IsCurrentPathFinished)
|
||||
bool isClose = sqrDist < MathUtils.Pow2(100);
|
||||
if (Character.CurrentHull == null || isClose && !isClosedDoor || pathSteering == null || IsCurrentPathUnreachable || IsCurrentPathFinished)
|
||||
{
|
||||
// Very close to the target, outside, or at the end of the path -> try to steer through the gap
|
||||
SteeringManager.Reset();
|
||||
pathSteering?.ResetPath();
|
||||
if (sqrDist < MathUtils.Pow2(50))
|
||||
{
|
||||
// Very close -> just keep steering forward
|
||||
var forward = VectorExtensions.Forward(Character.AnimController.Collider.Rotation + MathHelper.PiOver2);
|
||||
SteeringManager.SteeringManual(deltaTime, forward);
|
||||
}
|
||||
else if (Character.CurrentHull == null)
|
||||
Vector2 dir = Vector2.Normalize(diff);
|
||||
if (Character.CurrentHull == null || isClose)
|
||||
{
|
||||
// Outside -> steer away from the target
|
||||
SteeringManager.SteeringManual(deltaTime, Vector2.Normalize(-diff));
|
||||
if (EscapeTarget.FlowTargetHull != null)
|
||||
{
|
||||
SteeringManager.SteeringManual(deltaTime, Vector2.Normalize(EscapeTarget.WorldPosition - EscapeTarget.FlowTargetHull.WorldPosition));
|
||||
}
|
||||
else
|
||||
{
|
||||
SteeringManager.SteeringManual(deltaTime, -dir);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Still inside -> steer towards the target
|
||||
SteeringManager.SteeringManual(deltaTime, Vector2.Normalize(diff));
|
||||
SteeringManager.SteeringManual(deltaTime, dir);
|
||||
}
|
||||
return sqrDist < MathUtils.Pow2(200);
|
||||
return sqrDist < MathUtils.Pow2(250);
|
||||
}
|
||||
else if (pathSteering != null)
|
||||
{
|
||||
|
||||
@@ -250,7 +250,7 @@ namespace Barotrauma
|
||||
{
|
||||
rayEnd += SelectedAiTarget.Entity.Submarine.SimPosition;
|
||||
}
|
||||
UseIndoorSteeringOutside = Submarine.PickBody(SimPosition, rayEnd, collisionCategory: Physics.CollisionLevel) != null;
|
||||
UseIndoorSteeringOutside = Submarine.PickBody(SimPosition, rayEnd, collisionCategory: Physics.CollisionLevel | Physics.CollisionWall) != null;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -340,7 +340,7 @@ namespace Barotrauma
|
||||
IsInsideCave = Character.CurrentHull == null && Level.Loaded?.Caves.FirstOrDefault(c => c.Area.Contains(Character.WorldPosition)) is Level.Cave;
|
||||
}
|
||||
|
||||
if (UseIndoorSteeringOutside || IsInsideCave || Character.Submarine != null || hasValidPath && IsCloseEnoughToTarget(maxSteeringBuffer) || IsCloseEnoughToTarget(steeringBuffer))
|
||||
if (UseIndoorSteeringOutside || IsInsideCave || Character.CurrentHull?.Submarine != null || hasValidPath && IsCloseEnoughToTarget(maxSteeringBuffer) || IsCloseEnoughToTarget(steeringBuffer))
|
||||
{
|
||||
if (steeringManager != insideSteering)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Items.Components;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Linq;
|
||||
@@ -200,10 +201,14 @@ namespace Barotrauma
|
||||
currentTarget = target;
|
||||
Vector2 currentPos = host.SimPosition;
|
||||
pathFinder.InsideSubmarine = character.Submarine != null && !character.Submarine.Info.IsRuin;
|
||||
pathFinder.ApplyPenaltyToOutsideNodes = character.Submarine != null && character.PressureProtection <= 0;
|
||||
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)
|
||||
if (newPath.Unreachable || newPath.Nodes.None())
|
||||
{
|
||||
useNewPath = false;
|
||||
}
|
||||
else if (!useNewPath && currentPath != null && currentPath.CurrentNode != null)
|
||||
{
|
||||
// Check if the new path is the same as the old, in which case we just ignore it and continue using the old path (or the progress would reset).
|
||||
if (IsIdenticalPath())
|
||||
@@ -215,7 +220,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)
|
||||
if (!useNewPath && character.Submarine != null)
|
||||
{
|
||||
// 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.
|
||||
@@ -557,10 +562,14 @@ namespace Barotrauma
|
||||
{
|
||||
//the node we're heading towards is the last one in the path, and at a door
|
||||
//the door needs to be open for the character to reach the node
|
||||
if (currentWaypoint.ConnectedDoor.LinkedGap != null && currentWaypoint.ConnectedDoor.LinkedGap.IsRoomToRoom)
|
||||
if (currentWaypoint.ConnectedDoor.LinkedGap != null)
|
||||
{
|
||||
shouldBeOpen = true;
|
||||
door = currentWaypoint.ConnectedDoor;
|
||||
// Keep the airlock doors closed, but not in ruins/wrecks
|
||||
if (currentWaypoint.ConnectedDoor.LinkedGap.IsRoomToRoom || currentWaypoint.Submarine?.Info.IsRuin != null || currentWaypoint.Submarine?.Info.IsWreck != null)
|
||||
{
|
||||
shouldBeOpen = true;
|
||||
door = currentWaypoint.ConnectedDoor;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
+20
-4
@@ -39,6 +39,10 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
targetItem = character.Inventory.FindItemByTag(gearTag, true);
|
||||
if (targetItem == null && gearTag == LIGHT_DIVING_GEAR)
|
||||
{
|
||||
targetItem = character.Inventory.FindItemByTag(HEAVY_DIVING_GEAR, true);
|
||||
}
|
||||
if (targetItem == null || !character.HasEquippedItem(targetItem, slotType: InvSlotType.OuterClothes | InvSlotType.Head | InvSlotType.InnerClothes) && targetItem.ContainedItems.Any(i => i.HasTag(OXYGEN_SOURCE) && i.Condition > 0))
|
||||
{
|
||||
TryAddSubObjective(ref getDivingGear, () =>
|
||||
@@ -74,10 +78,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
// Seek oxygen that has at least 10% condition left, if we are inside a friendly sub.
|
||||
// The margin helps us to survive, because we might need some oxygen before we can find more oxygen.
|
||||
// When we are venturing outside of our sub, let's just suppose that we have enough oxygen with us and optimize it so that we don't keep switching off half used tanks.
|
||||
float min = character.Submarine != Submarine.MainSub ? 0.01f : MIN_OXYGEN;
|
||||
float min = GetMinOxygen(character);
|
||||
if (targetItem.OwnInventory != null && targetItem.OwnInventory.AllItems.None(it => it != null && it.HasTag(OXYGEN_SOURCE) && it.Condition > min))
|
||||
{
|
||||
TryAddSubObjective(ref getOxygen, () =>
|
||||
@@ -160,5 +161,20 @@ namespace Barotrauma
|
||||
getOxygen = null;
|
||||
targetItem = null;
|
||||
}
|
||||
|
||||
public static float GetMinOxygen(Character character)
|
||||
{
|
||||
// Seek oxygen that has at least 10% condition left, if we are inside a friendly sub.
|
||||
// The margin helps us to survive, because we might need some oxygen before we can find more oxygen.
|
||||
// When we are venturing outside of our sub, let's just suppose that we have enough oxygen with us and optimize it so that we don't keep switching off half used tanks.
|
||||
float min = 0.01f;
|
||||
float minOxygen = character.IsInFriendlySub ? MIN_OXYGEN : min;
|
||||
if (minOxygen > min && character.Inventory.AllItems.Any(i => i.HasTag("oxygensource") && i.ConditionPercentage >= minOxygen))
|
||||
{
|
||||
// There's a valid oxygen tank in the inventory -> no need to swap the tank too early.
|
||||
minOxygen = min;
|
||||
}
|
||||
return minOxygen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -55,8 +55,8 @@ namespace Barotrauma
|
||||
{
|
||||
if (HumanAIController.NeedsDivingGear(character.CurrentHull, out bool needsSuit) &&
|
||||
(needsSuit ?
|
||||
!HumanAIController.HasDivingSuit(character, conditionPercentage: AIObjectiveFindDivingGear.MIN_OXYGEN) :
|
||||
!HumanAIController.HasDivingGear(character, conditionPercentage: AIObjectiveFindDivingGear.MIN_OXYGEN)))
|
||||
!HumanAIController.HasDivingSuit(character, conditionPercentage: AIObjectiveFindDivingGear.GetMinOxygen(character)) :
|
||||
!HumanAIController.HasDivingGear(character, conditionPercentage: AIObjectiveFindDivingGear.GetMinOxygen(character))))
|
||||
{
|
||||
Priority = 100;
|
||||
}
|
||||
@@ -131,11 +131,11 @@ namespace Barotrauma
|
||||
bool needsEquipment = false;
|
||||
if (needsDivingSuit)
|
||||
{
|
||||
needsEquipment = !HumanAIController.HasDivingSuit(character, AIObjectiveFindDivingGear.MIN_OXYGEN);
|
||||
needsEquipment = !HumanAIController.HasDivingSuit(character, AIObjectiveFindDivingGear.GetMinOxygen(character));
|
||||
}
|
||||
else if (needsDivingGear)
|
||||
{
|
||||
needsEquipment = !HumanAIController.HasDivingGear(character, AIObjectiveFindDivingGear.MIN_OXYGEN);
|
||||
needsEquipment = !HumanAIController.HasDivingGear(character, AIObjectiveFindDivingGear.GetMinOxygen(character));
|
||||
}
|
||||
if (needsEquipment)
|
||||
{
|
||||
|
||||
+19
-6
@@ -260,7 +260,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
bool needsEquipment = false;
|
||||
float minOxygen = character.Submarine == null ? 0 : AIObjectiveFindDivingGear.MIN_OXYGEN;
|
||||
float minOxygen = AIObjectiveFindDivingGear.GetMinOxygen(character);
|
||||
if (needsDivingSuit)
|
||||
{
|
||||
needsEquipment = !HumanAIController.HasDivingSuit(character, minOxygen);
|
||||
@@ -374,7 +374,7 @@ namespace Barotrauma
|
||||
if (checkScooterTimer <= 0)
|
||||
{
|
||||
useScooter = false;
|
||||
checkScooterTimer = checkScooterTime;
|
||||
checkScooterTimer = checkScooterTime * Rand.Range(0.75f, 1.25f);
|
||||
string scooterTag = "scooter";
|
||||
string batteryTag = "mobilebattery";
|
||||
Item scooter = null;
|
||||
@@ -525,9 +525,22 @@ namespace Barotrauma
|
||||
{
|
||||
character.CursorPosition -= character.Submarine.Position;
|
||||
}
|
||||
Vector2 dir = Vector2.Normalize(character.CursorPosition - character.Position);
|
||||
if (!MathUtils.IsValid(dir)) { dir = Vector2.UnitY; }
|
||||
SteeringManager.SteeringManual(1.0f, dir);
|
||||
Vector2 diff = character.CursorPosition - character.Position;
|
||||
Vector2 dir = Vector2.Normalize(diff);
|
||||
float sqrDist = diff.LengthSquared();
|
||||
if (sqrDist > MathUtils.Pow2(CloseEnough * 1.5f))
|
||||
{
|
||||
SteeringManager.SteeringManual(1.0f, dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
float dot = Vector2.Dot(dir, VectorExtensions.Forward(character.AnimController.Collider.Rotation + MathHelper.PiOver2));
|
||||
bool isFacing = dot > 0.9f;
|
||||
if (!isFacing && sqrDist > MathUtils.Pow2(CloseEnough))
|
||||
{
|
||||
SteeringManager.SteeringManual(1.0f, dir);
|
||||
}
|
||||
}
|
||||
character.SetInput(InputType.Aim, false, true);
|
||||
character.SetInput(InputType.Shoot, false, true);
|
||||
}
|
||||
@@ -535,7 +548,7 @@ namespace Barotrauma
|
||||
|
||||
private bool useScooter;
|
||||
private float checkScooterTimer;
|
||||
private readonly float checkScooterTime = 0.2f;
|
||||
private readonly float checkScooterTime = 0.5f;
|
||||
|
||||
public Hull GetTargetHull() => GetTargetHull(Target);
|
||||
|
||||
|
||||
+3
-2
@@ -282,7 +282,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
newTargetTimer -= deltaTime;
|
||||
if (!character.IsClimbing && IsSteeringFinished())
|
||||
if (!character.IsClimbing && (PathSteering == null || PathSteering.CurrentPath == null || IsSteeringFinished()))
|
||||
{
|
||||
Wander(deltaTime);
|
||||
}
|
||||
@@ -393,9 +393,10 @@ namespace Barotrauma
|
||||
hullWeights.Clear();
|
||||
foreach (var hull in Hull.hullList)
|
||||
{
|
||||
if (character.Submarine == null) { break; }
|
||||
if (HumanAIController.UnsafeHulls.Contains(hull)) { continue; }
|
||||
if (hull.Submarine == null) { continue; }
|
||||
if (character.Submarine == null) { break; }
|
||||
if (hull.Submarine.Info.IsRuin || hull.Submarine.Info.IsWreck) { continue; }
|
||||
if (character.TeamID == CharacterTeamType.FriendlyNPC && !character.IsEscorted)
|
||||
{
|
||||
if (hull.Submarine.TeamID != character.TeamID)
|
||||
|
||||
+24
-1
@@ -88,6 +88,28 @@ namespace Barotrauma
|
||||
targetHull = d.Item.CurrentHull;
|
||||
break;
|
||||
}
|
||||
if (targetHull != null && !targetHull.IsTaggedAirlock())
|
||||
{
|
||||
// Target the closest airlock
|
||||
float closestDist = 0;
|
||||
Hull airlock = null;
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
if (hull.Submarine != targetHull.Submarine) { continue; }
|
||||
if (!hull.IsTaggedAirlock()) { continue; }
|
||||
float dist = Vector2.DistanceSquared(targetHull.Position, hull.Position);
|
||||
if (airlock == null || closestDist <= 0 || dist < closestDist)
|
||||
{
|
||||
airlock = hull;
|
||||
closestDist = dist;
|
||||
}
|
||||
|
||||
}
|
||||
if (airlock != null)
|
||||
{
|
||||
targetHull = airlock;
|
||||
}
|
||||
}
|
||||
if (targetHull != null)
|
||||
{
|
||||
RemoveSubObjective(ref moveInCaveObjective);
|
||||
@@ -95,7 +117,8 @@ namespace Barotrauma
|
||||
TryAddSubObjective(ref moveInsideObjective,
|
||||
constructor: () => new AIObjectiveGoTo(targetHull, character, objectiveManager)
|
||||
{
|
||||
AllowGoingOutside = true
|
||||
AllowGoingOutside = true,
|
||||
endNodeFilter = n => n.Waypoint.Submarine == targetHull.Submarine
|
||||
},
|
||||
onCompleted: () => RemoveSubObjective(ref moveInsideObjective),
|
||||
onAbandon: () => Abandon = true);
|
||||
|
||||
@@ -198,7 +198,7 @@ namespace Barotrauma
|
||||
}
|
||||
float xDiff = Math.Abs(start.X - node.TempPosition.X);
|
||||
float yDiff = Math.Abs(start.Y - node.TempPosition.Y);
|
||||
if (InsideSubmarine)
|
||||
if (InsideSubmarine && !(node.Waypoint.Submarine?.Info?.IsRuin ?? false))
|
||||
{
|
||||
//higher cost for vertical movement when inside the sub
|
||||
if (yDiff > 1.0f && node.Waypoint.Ladders == null && node.Waypoint.Stairs == null)
|
||||
@@ -215,6 +215,13 @@ namespace Barotrauma
|
||||
//much higher cost to waypoints that are outside
|
||||
if (node.Waypoint.CurrentHull == null && ApplyPenaltyToOutsideNodes) { node.TempDistance *= 10.0f; }
|
||||
|
||||
//optimization:
|
||||
//node extremely far, don't try to use it as a start node
|
||||
if (node.TempDistance > 800.0f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//prefer nodes that are closer to the end position
|
||||
node.TempDistance += (Math.Abs(end.X - node.TempPosition.X) + Math.Abs(end.Y - node.TempPosition.Y)) / 100.0f;
|
||||
|
||||
@@ -248,19 +255,17 @@ namespace Barotrauma
|
||||
PathNode startNode = null;
|
||||
foreach (PathNode node in sortedNodes)
|
||||
{
|
||||
if (startNode == null || node.TempDistance < startNode.TempDistance)
|
||||
if (nodeFilter != null && !nodeFilter(node)) { continue; }
|
||||
if (startNodeFilter != null && !startNodeFilter(node)) { continue; }
|
||||
// Always check the visibility for the start node
|
||||
if (!IsWaypointVisible(node, start)) { continue; }
|
||||
if (node.IsBlocked()) { continue; }
|
||||
if (node.Waypoint.ConnectedGap != null)
|
||||
{
|
||||
if (nodeFilter != null && !nodeFilter(node)) { continue; }
|
||||
if (startNodeFilter != null && !startNodeFilter(node)) { continue; }
|
||||
// Always check the visibility for the start node
|
||||
if (!IsWaypointVisible(node, start)) { continue; }
|
||||
if (node.IsBlocked()) { continue; }
|
||||
if (node.Waypoint.ConnectedGap != null)
|
||||
{
|
||||
if (!CanFitThroughGap(node.Waypoint.ConnectedGap, minGapSize)) { continue; }
|
||||
}
|
||||
startNode = node;
|
||||
if (!CanFitThroughGap(node.Waypoint.ConnectedGap, minGapSize)) { continue; }
|
||||
}
|
||||
startNode = node;
|
||||
break;
|
||||
}
|
||||
|
||||
if (startNode == null)
|
||||
@@ -301,19 +306,17 @@ namespace Barotrauma
|
||||
PathNode endNode = null;
|
||||
foreach (PathNode node in sortedNodes)
|
||||
{
|
||||
if (endNode == null || node.TempDistance < endNode.TempDistance)
|
||||
if (nodeFilter != null && !nodeFilter(node)) { continue; }
|
||||
if (endNodeFilter != null && !endNodeFilter(node)) { continue; }
|
||||
// Only check the visibility for the end node when allowed (fix leaks)
|
||||
if (!IsWaypointVisible(node, end, checkVisibility: checkVisibility)) { continue; }
|
||||
if (node.IsBlocked()) { continue; }
|
||||
if (node.Waypoint.ConnectedGap != null)
|
||||
{
|
||||
if (nodeFilter != null && !nodeFilter(node)) { continue; }
|
||||
if (endNodeFilter != null && !endNodeFilter(node)) { continue; }
|
||||
// Only check the visibility for the end node when allowed (fix leaks)
|
||||
if (!IsWaypointVisible(node, end, checkVisibility: checkVisibility)) { continue; }
|
||||
if (node.IsBlocked()) { continue; }
|
||||
if (node.Waypoint.ConnectedGap != null)
|
||||
{
|
||||
if (!CanFitThroughGap(node.Waypoint.ConnectedGap, minGapSize)) { continue; }
|
||||
}
|
||||
endNode = node;
|
||||
if (!CanFitThroughGap(node.Waypoint.ConnectedGap, minGapSize)) { continue; }
|
||||
}
|
||||
endNode = node;
|
||||
break;
|
||||
}
|
||||
|
||||
if (endNode == null)
|
||||
|
||||
@@ -1103,7 +1103,7 @@ namespace Barotrauma
|
||||
|
||||
public void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
if (!character.Enabled || Frozen || Invalid) { return; }
|
||||
if (!character.Enabled || character.Removed || Frozen || Invalid || Collider == null || Collider.Removed) { return; }
|
||||
|
||||
while (impactQueue.Count > 0)
|
||||
{
|
||||
|
||||
@@ -4579,9 +4579,9 @@ namespace Barotrauma
|
||||
|
||||
private readonly Dictionary<string, float> abilityResistances = new Dictionary<string, float>();
|
||||
|
||||
public float GetAbilityResistance(string resistanceId)
|
||||
public float GetAbilityResistance(AfflictionPrefab affliction)
|
||||
{
|
||||
return abilityResistances.TryGetValue(resistanceId, out float value) ? value : 1f;
|
||||
return abilityResistances.TryGetValue(affliction.Identifier, out float value) ? value : abilityResistances.TryGetValue(affliction.AfflictionType, out float typeValue) ? typeValue : 1f;
|
||||
}
|
||||
|
||||
public void ChangeAbilityResistance(string resistanceId, float value)
|
||||
|
||||
@@ -226,6 +226,15 @@ namespace Barotrauma
|
||||
return UnlockedTalents.Where(t => talentTree.TalentIsInTree(t));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Endocrine boosters can unlock talents outside the user's talent tree. This method is used to specifically get them
|
||||
/// </summary>
|
||||
public IEnumerable<string> GetEndocrineTalents()
|
||||
{
|
||||
if (!TalentTree.JobTalentTrees.TryGetValue(Job.Prefab.Identifier, out TalentTree talentTree)) { return Enumerable.Empty<string>(); }
|
||||
|
||||
return UnlockedTalents.Where(t => !talentTree.TalentIsInTree(t));
|
||||
}
|
||||
|
||||
public int AdditionalTalentPoints { get; set; }
|
||||
|
||||
@@ -1233,10 +1242,9 @@ namespace Barotrauma
|
||||
{
|
||||
Character?.CheckTalents(AbilityEffectType.OnGainMissionExperience, experienceGainMultiplier);
|
||||
}
|
||||
experienceGainMultiplier.Value += Character.GetStatValue(StatTypes.ExperienceGainMultiplier);
|
||||
experienceGainMultiplier.Value += Character?.GetStatValue(StatTypes.ExperienceGainMultiplier) ?? 0;
|
||||
|
||||
amount = (int)(amount * experienceGainMultiplier.Value);
|
||||
|
||||
if (amount < 0) { return; }
|
||||
|
||||
ExperiencePoints += amount;
|
||||
@@ -1252,8 +1260,8 @@ namespace Barotrauma
|
||||
OnExperienceChanged(prevAmount, ExperiencePoints);
|
||||
}
|
||||
|
||||
const int BaseExperienceRequired = 50;
|
||||
const int AddedExperienceRequiredPerLevel = 450;
|
||||
const int BaseExperienceRequired = -50;
|
||||
const int AddedExperienceRequiredPerLevel = 550;
|
||||
|
||||
public int GetTotalTalentPoints()
|
||||
{
|
||||
|
||||
@@ -458,7 +458,7 @@ namespace Barotrauma
|
||||
{
|
||||
resistance += afflictions[i].GetResistance(affliction);
|
||||
}
|
||||
return 1 - ((1 - resistance) * Character.GetAbilityResistance(affliction.Identifier));
|
||||
return 1 - ((1 - resistance) * Character.GetAbilityResistance(affliction));
|
||||
}
|
||||
|
||||
public float GetStatValue(StatTypes statType)
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ namespace Barotrauma.Abilities
|
||||
public CharacterAbilityGiveResistance(CharacterAbilityGroup characterAbilityGroup, XElement abilityElement) : base(characterAbilityGroup, abilityElement)
|
||||
{
|
||||
resistanceId = abilityElement.GetAttributeString("resistanceid", abilityElement.GetAttributeString("resistance", string.Empty));
|
||||
multiplier = abilityElement.GetAttributeFloat("multiplier", 1f);
|
||||
multiplier = abilityElement.GetAttributeFloat("multiplier", 1f); // rename this to resistance for consistency
|
||||
|
||||
if (string.IsNullOrEmpty(resistanceId))
|
||||
{
|
||||
|
||||
@@ -13,16 +13,5 @@ namespace Barotrauma
|
||||
{
|
||||
State = 1;
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
public override void ClientReadInitial(IReadMessage msg)
|
||||
{
|
||||
}
|
||||
#elif SERVER
|
||||
|
||||
public override void ServerWriteInitial(IWriteMessage msg, Client c)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,7 +347,7 @@ namespace Barotrauma
|
||||
if (!(GameMain.GameSession.GameMode is CampaignMode campaign)) { return; }
|
||||
int reward = GetReward(Submarine.MainSub);
|
||||
|
||||
float baseExperienceGain = reward * 0.1f;
|
||||
float baseExperienceGain = reward * 0.09f;
|
||||
|
||||
float difficultyMultiplier = 1 + level.Difficulty / 100f;
|
||||
baseExperienceGain *= difficultyMultiplier;
|
||||
|
||||
@@ -942,6 +942,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
doc.Root.Add(
|
||||
new XAttribute("gameversion", GameMain.Version.ToString()),
|
||||
new XAttribute("language", TextManager.Language),
|
||||
new XAttribute("masterserverurl", MasterServerUrl),
|
||||
new XAttribute("autocheckupdates", AutoCheckUpdates),
|
||||
|
||||
@@ -158,7 +158,7 @@ namespace Barotrauma.Items.Components
|
||||
if (!CanBeCombinedWith(otherGeneticMaterial)) { return false; }
|
||||
|
||||
float conditionIncrease = Rand.Range(ConditionIncreaseOnCombineMin, ConditionIncreaseOnCombineMax);
|
||||
conditionIncrease *= 1.0f + user.GetStatValue(StatTypes.GeneticMaterialRefineBonus);
|
||||
conditionIncrease += user.GetStatValue(StatTypes.GeneticMaterialRefineBonus);
|
||||
if (item.Prefab == otherGeneticMaterial.item.Prefab)
|
||||
{
|
||||
item.Condition = Math.Max(item.Condition, otherGeneticMaterial.item.Condition) + conditionIncrease;
|
||||
|
||||
@@ -781,7 +781,7 @@ namespace Barotrauma.Items.Components
|
||||
if (!aim)
|
||||
{
|
||||
var rope = GetRope();
|
||||
if (rope != null && rope.SnapWhenNotAimed)
|
||||
if (rope != null && rope.SnapWhenNotAimed && rope.Item.ParentInventory == null)
|
||||
{
|
||||
rope.Snap();
|
||||
}
|
||||
|
||||
@@ -198,7 +198,11 @@ namespace Barotrauma.Items.Components
|
||||
Vector2 barrelPos = TransformedBarrelPos + item.body.SimPosition;
|
||||
float rotation = (Item.body.Dir == 1.0f) ? Item.body.Rotation : Item.body.Rotation - MathHelper.Pi;
|
||||
float spread = GetSpread(character) * Rand.Range(-0.5f, 0.5f);
|
||||
LastProjectile?.Item.GetComponent<Rope>()?.Snap();
|
||||
var lastProjectile = LastProjectile;
|
||||
if (lastProjectile != projectile)
|
||||
{
|
||||
lastProjectile?.Item.GetComponent<Rope>()?.Snap();
|
||||
}
|
||||
float damageMultiplier = 1f + item.GetQualityModifier(Quality.StatType.AttackMultiplier);
|
||||
projectile.Shoot(character, character.AnimController.AimSourceSimPos, barrelPos, rotation + spread, ignoredBodies: limbBodies.ToList(), createNetworkEvent: false, damageMultiplier);
|
||||
projectile.Item.GetComponent<Rope>()?.Attach(Item, projectile.Item);
|
||||
|
||||
@@ -494,15 +494,12 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
float prevFireTimer = fireTimer;
|
||||
fireTimer += MathHelper.Lerp(deltaTime * 2.0f, deltaTime, item.Condition / item.MaxCondition);
|
||||
|
||||
|
||||
#if SERVER
|
||||
if (fireTimer > Math.Min(5.0f, FireDelay / 2) && blameOnBroken?.Character?.SelectedConstruction == item)
|
||||
{
|
||||
GameMain.Server.KarmaManager.OnReactorOverHeating(blameOnBroken.Character, deltaTime);
|
||||
GameMain.Server.KarmaManager.OnReactorOverHeating(item, blameOnBroken.Character, deltaTime);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fireTimer >= FireDelay && prevFireTimer < fireDelay)
|
||||
{
|
||||
new FireSource(item.WorldPosition);
|
||||
@@ -591,7 +588,7 @@ namespace Barotrauma.Items.Components
|
||||
GameServer.Log("Reactor meltdown!", ServerLog.MessageType.ItemInteraction);
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
GameMain.Server.KarmaManager.OnReactorMeltdown(blameOnBroken?.Character);
|
||||
GameMain.Server.KarmaManager.OnReactorMeltdown(item, blameOnBroken?.Character);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -614,10 +614,17 @@ namespace Barotrauma.Items.Components
|
||||
return;
|
||||
}
|
||||
|
||||
//target very far from the item -> update the item's transform to make sure it's inside the same sub as the target (or outside)
|
||||
if (Math.Abs(stickJoint.JointTranslation) > 100.0f)
|
||||
{
|
||||
item.UpdateTransform();
|
||||
}
|
||||
|
||||
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
if (StickTargetRemoved() ||
|
||||
(!StickPermanently && (stickJoint.JointTranslation < stickJoint.LowerLimit * 0.9f || stickJoint.JointTranslation > stickJoint.UpperLimit * 0.9f)))
|
||||
(!StickPermanently && (stickJoint.JointTranslation < stickJoint.LowerLimit * 0.9f || stickJoint.JointTranslation > stickJoint.UpperLimit * 0.9f)) ||
|
||||
Math.Abs(stickJoint.JointTranslation) > 100.0f) //failsafe unstick if the target is still extremely far
|
||||
{
|
||||
Unstick();
|
||||
#if SERVER
|
||||
|
||||
@@ -406,15 +406,7 @@ namespace Barotrauma.Items.Components
|
||||
fixDuration /= 1 + CurrentFixer.GetStatValue(StatTypes.RepairSpeed) + currentRepairItem?.Prefab.AddedRepairSpeedMultiplier ?? 0f;
|
||||
fixDuration /= 1 + item.GetQualityModifier(Quality.StatType.RepairSpeed);
|
||||
|
||||
// kind of rough to keep this in update, but seems most robust
|
||||
if (requiredSkills.Any(s => s != null && s.Identifier.Equals("mechanical", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
item.MaxRepairConditionMultiplier = 1 + CurrentFixer.GetStatValue(StatTypes.MaxRepairConditionMultiplierMechanical);
|
||||
}
|
||||
if (requiredSkills.Any(s => s != null && s.Identifier.Equals("electrical", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
item.MaxRepairConditionMultiplier = 1 + CurrentFixer.GetStatValue(StatTypes.MaxRepairConditionMultiplierElectrical);
|
||||
}
|
||||
item.MaxRepairConditionMultiplier = GetMaxRepairConditionMultiplier(CurrentFixer);
|
||||
|
||||
if (currentFixerAction == FixActions.Repair)
|
||||
{
|
||||
@@ -489,6 +481,21 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private float GetMaxRepairConditionMultiplier(Character character)
|
||||
{
|
||||
if (character == null) { return 1.0f; }
|
||||
// kind of rough to keep this in update, but seems most robust
|
||||
if (requiredSkills.Any(s => s != null && s.Identifier.Equals("mechanical", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return 1 + character.GetStatValue(StatTypes.MaxRepairConditionMultiplierMechanical);
|
||||
}
|
||||
if (requiredSkills.Any(s => s != null && s.Identifier.Equals("electrical", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return 1 + character.GetStatValue(StatTypes.MaxRepairConditionMultiplierElectrical);
|
||||
}
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
private bool IsTinkerable(Character character)
|
||||
{
|
||||
if (!character.HasAbilityFlag(AbilityFlags.CanTinker)) { return false; }
|
||||
|
||||
@@ -95,6 +95,10 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
snapped = value;
|
||||
if (!snapped)
|
||||
{
|
||||
snapTimer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,6 +117,7 @@ namespace Barotrauma.Items.Components
|
||||
System.Diagnostics.Debug.Assert(target != null);
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
Snapped = false;
|
||||
ApplyStatusEffects(ActionType.OnUse, 1.0f, worldPosition: item.WorldPosition);
|
||||
IsActive = true;
|
||||
}
|
||||
@@ -148,6 +153,7 @@ namespace Barotrauma.Items.Components
|
||||
#endif
|
||||
var projectile = target.GetComponent<Projectile>();
|
||||
if (projectile == null) { return; }
|
||||
|
||||
if (SnapOnCollision)
|
||||
{
|
||||
raycastTimer += deltaTime;
|
||||
|
||||
@@ -1323,7 +1323,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
Submarine = parentInventory.Owner.Submarine;
|
||||
if (body != null) body.Submarine = Submarine;
|
||||
if (body != null) { body.Submarine = Submarine; }
|
||||
|
||||
return CurrentHull;
|
||||
}
|
||||
@@ -1733,10 +1733,18 @@ namespace Barotrauma
|
||||
public void UpdateTransform()
|
||||
{
|
||||
if (body == null) { return; }
|
||||
|
||||
Submarine prevSub = Submarine;
|
||||
|
||||
FindHull();
|
||||
var projectile = GetComponent<Projectile>();
|
||||
if (projectile?.StickTarget?.UserData is Limb limb)
|
||||
{
|
||||
Submarine = body.Submarine = limb.character?.Submarine;
|
||||
currentHull = limb.character?.CurrentHull;
|
||||
}
|
||||
else
|
||||
{
|
||||
FindHull();
|
||||
}
|
||||
|
||||
if (Submarine == null && prevSub != null)
|
||||
{
|
||||
@@ -1814,6 +1822,12 @@ namespace Barotrauma
|
||||
{
|
||||
if (transformDirty) { return false; }
|
||||
|
||||
var projectile = GetComponent<Projectile>();
|
||||
if (projectile?.IgnoredBodies != null)
|
||||
{
|
||||
if (projectile.IgnoredBodies.Contains(f2.Body)) { return false; }
|
||||
}
|
||||
|
||||
contact.GetWorldManifold(out Vector2 normal, out _);
|
||||
if (contact.FixtureA.Body == f1.Body) { normal = -normal; }
|
||||
float impact = Vector2.Dot(f1.Body.LinearVelocity, -normal);
|
||||
|
||||
@@ -1964,11 +1964,11 @@ namespace Barotrauma
|
||||
Vector2 entranceDir = Vector2.Zero;
|
||||
if (g.IsHorizontal)
|
||||
{
|
||||
entranceDir = Vector2.UnitX * Math.Sign(g.WorldPosition.X - g.linkedTo[0].WorldPosition.X);
|
||||
entranceDir = Vector2.UnitX * 2 * Math.Sign(g.WorldPosition.X - g.linkedTo[0].WorldPosition.X);
|
||||
}
|
||||
else
|
||||
{
|
||||
entranceDir = Vector2.UnitY * Math.Sign(g.WorldPosition.Y - g.linkedTo[0].WorldPosition.Y);
|
||||
entranceDir = Vector2.UnitY * 2 * Math.Sign(g.WorldPosition.Y - g.linkedTo[0].WorldPosition.Y);
|
||||
}
|
||||
var entranceWayPoint = new WayPoint(g.WorldPosition + entranceDir * 64.0f, SpawnType.Path, null)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user