Merge remote-tracking branch 'upstream/master' into develop
This commit is contained in:
+38
-23
@@ -1,4 +1,6 @@
|
||||
#nullable enable
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -117,24 +119,52 @@ namespace Barotrauma
|
||||
{
|
||||
if (inspectTimer > 0.0f)
|
||||
{
|
||||
character.SelectCharacter(Target);
|
||||
Vector2 diff = Target.WorldPosition - character.WorldPosition;
|
||||
float dist = diff.Length();
|
||||
float maxDist = ConvertUnits.ToDisplayUnits(HumanoidAnimController.BreakFromGrabDistance);
|
||||
if (dist > maxDist)
|
||||
{
|
||||
if (dist > maxDist * 2 || !character.CanSeeTarget(Target, seeThroughWindows: false))
|
||||
{
|
||||
//too far to reach by small manual movement, need to switch back to the earlier state
|
||||
currentState = State.GotoTarget;
|
||||
}
|
||||
//move closer horizontally if the horizontal distance is the issue
|
||||
else if (Math.Abs(diff.X) > Math.Abs(diff.Y) * 2.0f)
|
||||
{
|
||||
character.AIController.SteeringManager.SteeringManual(deltaTime, new Vector2(MathF.Sign(Target.WorldPosition.X - character.WorldPosition.X), 0.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
character.AIController.SteeringManager.Reset();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dist < maxDist * 0.5f) { character.AIController.SteeringManager.Reset(); }
|
||||
character.SelectCharacter(Target);
|
||||
}
|
||||
|
||||
inspectTimer -= deltaTime;
|
||||
if (inspectTimer < InspectTime - 1)
|
||||
{
|
||||
if (Target.AnimController.IsMovingFast)
|
||||
if (Math.Abs(Target.AnimController.TargetMovement.X) > 1.0f)
|
||||
{
|
||||
ArrestFleeing();
|
||||
}
|
||||
else if (Math.Abs(Target.AnimController.TargetMovement.X) > 1.0f)
|
||||
{
|
||||
// If the target moves, reset the inspect timer and tell to hold still
|
||||
// If the target moves, tell to hold still
|
||||
character.Speak(TextManager.Get("dialogcheckstolenitems.holdstill").Value, identifier: "holdstill".ToIdentifier(), minDurationBetweenSimilar: 3f);
|
||||
inspectTimer = InspectTime;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (character.SelectedCharacter != Target)
|
||||
{
|
||||
//target not selected -> must've escaped
|
||||
Abandon = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (stolenItems.Any() &&
|
||||
Rand.Range(0.0f, 1.0f, Rand.RandSync.Unsynced) < FindStolenItemsProbability)
|
||||
{
|
||||
@@ -155,13 +185,6 @@ namespace Barotrauma
|
||||
if (warnTimer > 0.0f)
|
||||
{
|
||||
warnTimer -= deltaTime;
|
||||
if (warnTimer < currentWarnDelay - 1)
|
||||
{
|
||||
if (Target.AnimController.IsMovingFast)
|
||||
{
|
||||
ArrestFleeing();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
var stolenItemsOnCharacter = stolenItems.Where(it => it.GetRootInventoryOwner() == Target);
|
||||
@@ -189,14 +212,6 @@ namespace Barotrauma
|
||||
IsCompleted = true;
|
||||
}
|
||||
|
||||
private void ArrestFleeing()
|
||||
{
|
||||
character.Speak(TextManager.Get("dialogcheckstolenitems.arrest").Value);
|
||||
currentState = State.Done;
|
||||
IsCompleted = true;
|
||||
Arrest(abortWhenItemsDropped: false, allowHoldFire: false);
|
||||
}
|
||||
|
||||
private void Arrest(bool abortWhenItemsDropped, bool allowHoldFire)
|
||||
{
|
||||
bool isCriminal = Target.IsCriminal;
|
||||
|
||||
+2
@@ -12,6 +12,8 @@ namespace Barotrauma
|
||||
protected override float TargetUpdateTimeMultiplier => 0.2f;
|
||||
public bool TargetCharactersInOtherSubs { get; init; }
|
||||
|
||||
protected override bool AllowInAnySub => TargetCharactersInOtherSubs;
|
||||
|
||||
public AIObjectiveFightIntruders(Character character, AIObjectiveManager objectiveManager, float priorityModifier = 1)
|
||||
: base(character, objectiveManager, priorityModifier) { }
|
||||
|
||||
|
||||
+3
-1
@@ -21,6 +21,8 @@ namespace Barotrauma
|
||||
private const float MaxSpeedOnStairs = 1.7f;
|
||||
private const float SteepSlopePushMagnitude = MaxSpeedOnStairs;
|
||||
|
||||
public const float BreakFromGrabDistance = 1.4f;
|
||||
|
||||
public override RagdollParams RagdollParams
|
||||
{
|
||||
get { return HumanRagdollParams; }
|
||||
@@ -1844,7 +1846,7 @@ namespace Barotrauma
|
||||
|
||||
float dist = ConvertUnits.ToSimUnits(Vector2.Distance(target.WorldPosition, WorldPosition));
|
||||
//let the target break free if it's moving away and gets far enough
|
||||
if ((GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient) && dist > 1.4f && target.AllowInput &&
|
||||
if ((GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient) && dist > BreakFromGrabDistance && target.AllowInput &&
|
||||
Vector2.Dot(target.WorldPosition - WorldPosition, target.AnimController.TargetMovement) > 0)
|
||||
{
|
||||
character.DeselectCharacter();
|
||||
|
||||
@@ -299,6 +299,7 @@ namespace Barotrauma
|
||||
public XElement OrderData;
|
||||
|
||||
public bool PermanentlyDead;
|
||||
public bool RenamingEnabled = false;
|
||||
|
||||
private static ushort idCounter = 1;
|
||||
private const string disguiseName = "???";
|
||||
@@ -802,6 +803,7 @@ namespace Barotrauma
|
||||
LoadTagsBackwardsCompatibility(infoElement, tags);
|
||||
SpeciesName = infoElement.GetAttributeIdentifier("speciesname", "");
|
||||
PermanentlyDead = infoElement.GetAttributeBool("permanentlydead", false);
|
||||
RenamingEnabled = infoElement.GetAttributeBool("renamingenabled", false);
|
||||
ContentXElement element;
|
||||
if (!SpeciesName.IsEmpty)
|
||||
{
|
||||
@@ -1499,7 +1501,8 @@ namespace Barotrauma
|
||||
new XAttribute("startitemsgiven", StartItemsGiven),
|
||||
new XAttribute("personality", PersonalityTrait?.Identifier ?? Identifier.Empty),
|
||||
new XAttribute("lastrewarddistribution", LastRewardDistribution.Match(some: value => value, none: () => -1).ToString()),
|
||||
new XAttribute("permanentlydead", PermanentlyDead)
|
||||
new XAttribute("permanentlydead", PermanentlyDead),
|
||||
new XAttribute("renamingenabled", RenamingEnabled)
|
||||
);
|
||||
|
||||
if (HumanPrefabIds != default)
|
||||
|
||||
@@ -7,9 +7,14 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Responsible for keeping track of the characters in the player crew, saving and loading their orders, managing the crew list UI
|
||||
/// </summary>
|
||||
partial class CrewManager
|
||||
{
|
||||
const float ConversationIntervalMin = 100.0f;
|
||||
@@ -27,7 +32,10 @@ namespace Barotrauma
|
||||
{
|
||||
return characters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Note: this only returns AI characters' infos in multiplayer. The infos are used to manage hiring/firing/renaming, which only applies to AI characters.
|
||||
/// Use <see cref="GetSessionCrewCharacters"/> to get all the characters regardless if they're player or AI controlled.
|
||||
/// </summary>
|
||||
public IEnumerable<CharacterInfo> GetCharacterInfos()
|
||||
{
|
||||
return characterInfos;
|
||||
@@ -387,15 +395,8 @@ namespace Barotrauma
|
||||
|
||||
public void RenameCharacter(CharacterInfo characterInfo, string newName)
|
||||
{
|
||||
int identifier = characterInfo.GetIdentifierUsingOriginalName();
|
||||
var match = characterInfos.FirstOrDefault(ci => ci.GetIdentifierUsingOriginalName() == identifier);
|
||||
if (match == null)
|
||||
{
|
||||
DebugConsole.ThrowError($"Tried to rename an invalid crew member ({identifier})");
|
||||
return;
|
||||
}
|
||||
match.Rename(newName);
|
||||
RenameCharacterProjSpecific(match);
|
||||
characterInfo.Rename(newName);
|
||||
RenameCharacterProjSpecific(characterInfo);
|
||||
}
|
||||
|
||||
partial void RenameCharacterProjSpecific(CharacterInfo characterInfo);
|
||||
|
||||
@@ -211,7 +211,7 @@ namespace Barotrauma
|
||||
|
||||
public virtual bool TryPurchase(Client client, int price)
|
||||
{
|
||||
return GetWallet(client).TryDeduct(price);
|
||||
return price == 0 || GetWallet(client).TryDeduct(price);
|
||||
}
|
||||
|
||||
public virtual int GetBalance(Client client = null)
|
||||
@@ -250,6 +250,19 @@ namespace Barotrauma
|
||||
(sub.AtEndExit != leavingSub.AtEndExit || sub.AtStartExit != leavingSub.AtStartExit));
|
||||
}
|
||||
|
||||
public SubmarineInfo GetPredefinedStartOutpost()
|
||||
{
|
||||
if (Map?.CurrentLocation?.Type?.GetForcedOutpostGenerationParams() is OutpostGenerationParams parameters &&
|
||||
!parameters.OutpostFilePath.IsNullOrEmpty())
|
||||
{
|
||||
return new SubmarineInfo(parameters.OutpostFilePath.Value)
|
||||
{
|
||||
OutpostGenerationParams = parameters
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
base.Start();
|
||||
@@ -1044,7 +1057,7 @@ namespace Barotrauma
|
||||
return ToolBox.SelectWeightedRandom(factionsList, weights, random);
|
||||
}
|
||||
|
||||
public bool TryHireCharacter(Location location, CharacterInfo characterInfo, bool takeMoney = true, Client client = null)
|
||||
public bool TryHireCharacter(Location location, CharacterInfo characterInfo, bool takeMoney = true, Client client = null, bool buyingNewCharacter = false)
|
||||
{
|
||||
if (characterInfo == null) { return false; }
|
||||
if (characterInfo.MinReputationToHire.factionId != Identifier.Empty)
|
||||
@@ -1054,7 +1067,8 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (takeMoney && !TryPurchase(client, HireManager.GetSalaryFor(characterInfo))) { return false; }
|
||||
var price = buyingNewCharacter ? NewCharacterCost(characterInfo) : HireManager.GetSalaryFor(characterInfo);
|
||||
if (takeMoney && !TryPurchase(client, price)) { return false; }
|
||||
|
||||
characterInfo.IsNewHire = true;
|
||||
characterInfo.Title = null;
|
||||
@@ -1063,6 +1077,17 @@ namespace Barotrauma
|
||||
GameAnalyticsManager.AddMoneySpentEvent(characterInfo.Salary, GameAnalyticsManager.MoneySink.Crew, characterInfo.Job?.Prefab.Identifier.Value ?? "unknown");
|
||||
return true;
|
||||
}
|
||||
|
||||
public int NewCharacterCost(CharacterInfo characterInfo)
|
||||
{
|
||||
float characterCostPercentage = GameMain.NetworkMember?.ServerSettings.ReplaceCostPercentage ?? 100f;
|
||||
return (int)MathF.Round(HireManager.GetSalaryFor(characterInfo) * (characterCostPercentage/100f));
|
||||
}
|
||||
|
||||
public bool CanAffordNewCharacter(CharacterInfo characterInfo)
|
||||
{
|
||||
return CanAfford(NewCharacterCost(characterInfo));
|
||||
}
|
||||
|
||||
private void NPCInteract(Character npc, Character interactor)
|
||||
{
|
||||
|
||||
@@ -574,6 +574,12 @@ namespace Barotrauma
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + (Level.Loaded?.LevelData?.Biome?.Identifier.Value ?? "none") + "Discovered:Playtime", campaignMode.TotalPlayTime);
|
||||
GameAnalyticsManager.AddDesignEvent(eventId + (Level.Loaded?.LevelData?.Biome?.Identifier.Value ?? "none") + "Discovered:PassedLevels", campaignMode.TotalPassedLevels);
|
||||
}
|
||||
if (GameMain.NetworkMember?.ServerSettings is { } serverSettings)
|
||||
{
|
||||
GameAnalyticsManager.AddDesignEvent("ServerSettings:RespawnMode:" + serverSettings.RespawnMode);
|
||||
GameAnalyticsManager.AddDesignEvent("ServerSettings:IronmanMode:" + serverSettings.IronmanMode);
|
||||
GameAnalyticsManager.AddDesignEvent("ServerSettings:AllowBotTakeoverOnPermadeath:" + serverSettings.AllowBotTakeoverOnPermadeath);
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
@@ -479,6 +479,16 @@ namespace Barotrauma.Networking
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize(100f, IsPropertySaveable.Yes)]
|
||||
/// <summary>
|
||||
/// Percentage modifier for the cost of hiring a new character to replace a permanently killed one.
|
||||
/// </summary>
|
||||
public float ReplaceCostPercentage
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize(true, IsPropertySaveable.Yes)]
|
||||
/// <summary>
|
||||
@@ -651,6 +661,8 @@ namespace Barotrauma.Networking
|
||||
set
|
||||
{
|
||||
if (respawnMode == value) { return; }
|
||||
//can't change this when a round is running (but clients can, if the server says so, e.g. when a client joins and needs to know what it's set to despite a round being running)
|
||||
if (GameMain.NetworkMember is { GameStarted: true, IsServer: true }) { return; }
|
||||
respawnMode = value;
|
||||
ServerDetailsChanged = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user